1 // Copyright 2018 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 "services/network/proxy_auto_config_library.h"
6 
7 #include "net/base/address_list.h"
8 #include "net/base/net_errors.h"
9 #include "net/base/network_interfaces.h"
10 #include "net/log/net_log_with_source.h"
11 #include "net/socket/client_socket_factory.h"
12 #include "net/socket/client_socket_handle.h"
13 #include "net/socket/datagram_client_socket.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace network {
18 namespace {
19 
20 // Helper for verifying whether the address list returned by myIpAddress() /
21 // myIpAddressEx() looks correct.
VerifyActualMyIpAddresses(const net::IPAddressList & test_list)22 void VerifyActualMyIpAddresses(const net::IPAddressList& test_list) {
23   // Enumerate all of the IP addresses for the system (skipping loopback and
24   // link-local ones). This is used as a reference implementation to check
25   // whether |test_list| (which was obtained using a different strategy) looks
26   // correct.
27   std::set<net::IPAddress> candidates;
28   net::NetworkInterfaceList networks;
29   net::GetNetworkList(&networks, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
30   for (const auto& network : networks) {
31     if (network.address.IsLinkLocal() || network.address.IsLoopback())
32       continue;
33     candidates.insert(network.address);
34   }
35 
36   // Ordinarily the machine running this test will have an IP address. However
37   // for some bot configurations (notably Android) that may not be the case.
38   EXPECT_EQ(candidates.empty(), test_list.empty());
39 
40   // |test_list| should be a subset of |candidates|.
41   for (const auto& ip : test_list)
42     EXPECT_EQ(1u, candidates.count(ip));
43 }
44 
45 // Tests for PacMyIpAddress() and PacMyIpAddressEx().
TEST(PacLibraryTest,ActualPacMyIpAddress)46 TEST(PacLibraryTest, ActualPacMyIpAddress) {
47   auto my_ip_addresses = PacMyIpAddress();
48 
49   VerifyActualMyIpAddresses(my_ip_addresses);
50 }
51 
TEST(PacLibraryTest,ActualPacMyIpAddressEx)52 TEST(PacLibraryTest, ActualPacMyIpAddressEx) {
53   VerifyActualMyIpAddresses(PacMyIpAddressEx());
54 }
55 
CreateIPAddress(base::StringPiece literal)56 net::IPAddress CreateIPAddress(base::StringPiece literal) {
57   net::IPAddress result;
58   if (!result.AssignFromIPLiteral(literal)) {
59     ADD_FAILURE() << "Failed parsing IP: " << literal;
60     return net::IPAddress();
61   }
62   return result;
63 }
64 
CreateAddressList(const std::vector<base::StringPiece> & ip_literals)65 net::AddressList CreateAddressList(
66     const std::vector<base::StringPiece>& ip_literals) {
67   net::AddressList result;
68   for (const auto& ip : ip_literals)
69     result.push_back(net::IPEndPoint(CreateIPAddress(ip), 8080));
70   return result;
71 }
72 
73 class MockUDPSocket : public net::DatagramClientSocket {
74  public:
MockUDPSocket(const net::IPAddress & peer_ip,const net::IPAddress & local_ip,net::Error connect_error)75   MockUDPSocket(const net::IPAddress& peer_ip,
76                 const net::IPAddress& local_ip,
77                 net::Error connect_error)
78       : peer_ip_(peer_ip), local_ip_(local_ip), connect_error_(connect_error) {}
79 
80   ~MockUDPSocket() override = default;
81 
82   // Socket implementation.
Read(net::IOBuffer * buf,int buf_len,net::CompletionOnceCallback callback)83   int Read(net::IOBuffer* buf,
84            int buf_len,
85            net::CompletionOnceCallback callback) override {
86     ADD_FAILURE() << "Called Read()";
87     return net::ERR_UNEXPECTED;
88   }
Write(net::IOBuffer * buf,int buf_len,net::CompletionOnceCallback callback,const net::NetworkTrafficAnnotationTag & traffic_annotation)89   int Write(
90       net::IOBuffer* buf,
91       int buf_len,
92       net::CompletionOnceCallback callback,
93       const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
94     ADD_FAILURE() << "Called Read()";
95     return net::ERR_UNEXPECTED;
96   }
SetReceiveBufferSize(int32_t size)97   int SetReceiveBufferSize(int32_t size) override {
98     ADD_FAILURE() << "Called SetReceiveBufferSize()";
99     return net::ERR_UNEXPECTED;
100   }
SetSendBufferSize(int32_t size)101   int SetSendBufferSize(int32_t size) override {
102     ADD_FAILURE() << "Called SetSendBufferSize()";
103     return net::ERR_UNEXPECTED;
104   }
105 
106   // net::DatagramSocket implementation.
Close()107   void Close() override { ADD_FAILURE() << "Called Close()"; }
GetPeerAddress(net::IPEndPoint * address) const108   int GetPeerAddress(net::IPEndPoint* address) const override {
109     ADD_FAILURE() << "Called GetPeerAddress()";
110     return net::ERR_UNEXPECTED;
111   }
GetLocalAddress(net::IPEndPoint * address) const112   int GetLocalAddress(net::IPEndPoint* address) const override {
113     if (connect_error_ != net::OK)
114       return connect_error_;
115 
116     *address = net::IPEndPoint(local_ip_, 8080);
117     return net::OK;
118   }
UseNonBlockingIO()119   void UseNonBlockingIO() override {
120     ADD_FAILURE() << "Called UseNonBlockingIO()";
121   }
SetDoNotFragment()122   int SetDoNotFragment() override {
123     ADD_FAILURE() << "Called SetDoNotFragment()";
124     return net::ERR_UNEXPECTED;
125   }
SetMsgConfirm(bool confirm)126   void SetMsgConfirm(bool confirm) override {
127     ADD_FAILURE() << "Called SetMsgConfirm()";
128   }
NetLog() const129   const net::NetLogWithSource& NetLog() const override {
130     ADD_FAILURE() << "Called net::NetLog()";
131     return net_log_;
132   }
133 
134   // net::DatagramClientSocket implementation.
Connect(const net::IPEndPoint & address)135   int Connect(const net::IPEndPoint& address) override {
136     EXPECT_EQ(peer_ip_.ToString(), address.address().ToString());
137     return connect_error_;
138   }
ConnectUsingNetwork(net::NetworkChangeNotifier::NetworkHandle network,const net::IPEndPoint & address)139   int ConnectUsingNetwork(net::NetworkChangeNotifier::NetworkHandle network,
140                           const net::IPEndPoint& address) override {
141     ADD_FAILURE() << "Called ConnectUsingNetwork()";
142     return net::ERR_UNEXPECTED;
143   }
ConnectUsingDefaultNetwork(const net::IPEndPoint & address)144   int ConnectUsingDefaultNetwork(const net::IPEndPoint& address) override {
145     ADD_FAILURE() << "Called ConnectUsingDefaultNetwork()";
146     return net::ERR_UNEXPECTED;
147   }
GetBoundNetwork() const148   net::NetworkChangeNotifier::NetworkHandle GetBoundNetwork() const override {
149     ADD_FAILURE() << "Called GetBoundNetwork()";
150     return network_;
151   }
ApplySocketTag(const net::SocketTag & tag)152   void ApplySocketTag(const net::SocketTag& tag) override {
153     ADD_FAILURE() << "Called ApplySocketTag()";
154   }
WriteAsync(net::DatagramBuffers buffers,net::CompletionOnceCallback callback,const net::NetworkTrafficAnnotationTag & traffic_annotation)155   int WriteAsync(
156       net::DatagramBuffers buffers,
157       net::CompletionOnceCallback callback,
158       const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
159     ADD_FAILURE() << "Called WriteAsync()";
160     return net::ERR_UNEXPECTED;
161   }
WriteAsync(const char * buffer,size_t buf_len,net::CompletionOnceCallback callback,const net::NetworkTrafficAnnotationTag & traffic_annotation)162   int WriteAsync(
163       const char* buffer,
164       size_t buf_len,
165       net::CompletionOnceCallback callback,
166       const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
167     ADD_FAILURE() << "Called WriteAsync()";
168     return net::ERR_UNEXPECTED;
169   }
GetUnwrittenBuffers()170   net::DatagramBuffers GetUnwrittenBuffers() override {
171     ADD_FAILURE() << "Called GetUnwrittenBuffers()";
172     return net::DatagramBuffers();
173   }
SetWriteAsyncEnabled(bool enabled)174   void SetWriteAsyncEnabled(bool enabled) override {
175     ADD_FAILURE() << "Called SetWriteAsyncEnabled()";
176   }
SetMaxPacketSize(size_t max_packet_size)177   void SetMaxPacketSize(size_t max_packet_size) override {
178     ADD_FAILURE() << "Called SetWriteAsyncEnabled()";
179   }
WriteAsyncEnabled()180   bool WriteAsyncEnabled() override {
181     ADD_FAILURE() << "Called WriteAsyncEnabled()";
182     return false;
183   }
SetWriteMultiCoreEnabled(bool enabled)184   void SetWriteMultiCoreEnabled(bool enabled) override {
185     ADD_FAILURE() << "Called SetWriteMultiCoreEnabled()";
186   }
SetSendmmsgEnabled(bool enabled)187   void SetSendmmsgEnabled(bool enabled) override {
188     ADD_FAILURE() << "Called SetSendmmsgEnabled()";
189   }
SetWriteBatchingActive(bool active)190   void SetWriteBatchingActive(bool active) override {
191     ADD_FAILURE() << "Called SetWriteBatchingActive()";
192   }
SetMulticastInterface(uint32_t interface_index)193   int SetMulticastInterface(uint32_t interface_index) override {
194     ADD_FAILURE() << "Called SetMulticastInterface()";
195     return net::ERR_UNEXPECTED;
196   }
197 
198  private:
199   net::NetLogWithSource net_log_;
200   net::NetworkChangeNotifier::NetworkHandle network_;
201 
202   net::IPAddress peer_ip_;
203   net::IPAddress local_ip_;
204   net::Error connect_error_;
205 
206   DISALLOW_COPY_AND_ASSIGN(MockUDPSocket);
207 };
208 
209 class MockSocketFactory : public net::ClientSocketFactory {
210  public:
211   MockSocketFactory() = default;
212 
AddUDPConnectSuccess(base::StringPiece peer_ip_literal,base::StringPiece local_ip_literal)213   void AddUDPConnectSuccess(base::StringPiece peer_ip_literal,
214                             base::StringPiece local_ip_literal) {
215     auto peer_ip = CreateIPAddress(peer_ip_literal);
216     auto local_ip = CreateIPAddress(local_ip_literal);
217 
218     // The address family of local and peer IP must match.
219     ASSERT_EQ(peer_ip.size(), local_ip.size());
220 
221     udp_sockets_.push_back(
222         std::make_unique<MockUDPSocket>(peer_ip, local_ip, net::OK));
223   }
224 
AddUDPConnectFailure(base::StringPiece peer_ip)225   void AddUDPConnectFailure(base::StringPiece peer_ip) {
226     udp_sockets_.push_back(std::make_unique<MockUDPSocket>(
227         CreateIPAddress(peer_ip), net::IPAddress(),
228         net::ERR_ADDRESS_UNREACHABLE));
229   }
230 
~MockSocketFactory()231   ~MockSocketFactory() override {
232     EXPECT_EQ(0u, udp_sockets_.size())
233         << "Not all of the mock sockets were consumed.";
234   }
235 
236   // net::ClientSocketFactory
CreateDatagramClientSocket(net::DatagramSocket::BindType bind_type,net::NetLog * net_log,const net::NetLogSource & source)237   std::unique_ptr<net::DatagramClientSocket> CreateDatagramClientSocket(
238       net::DatagramSocket::BindType bind_type,
239       net::NetLog* net_log,
240       const net::NetLogSource& source) override {
241     if (udp_sockets_.empty()) {
242       ADD_FAILURE() << "Not enough mock UDP sockets";
243       return nullptr;
244     }
245 
246     auto result = std::move(udp_sockets_.front());
247     udp_sockets_.erase(udp_sockets_.begin());
248     return result;
249   }
CreateTransportClientSocket(const net::AddressList & addresses,std::unique_ptr<net::SocketPerformanceWatcher> socket_performance_watcher,net::NetLog * net_log,const net::NetLogSource & source)250   std::unique_ptr<net::TransportClientSocket> CreateTransportClientSocket(
251       const net::AddressList& addresses,
252       std::unique_ptr<net::SocketPerformanceWatcher> socket_performance_watcher,
253       net::NetLog* net_log,
254       const net::NetLogSource& source) override {
255     ADD_FAILURE() << "Called CreateTransportClientSocket()";
256     return nullptr;
257   }
CreateSSLClientSocket(net::SSLClientContext * context,std::unique_ptr<net::StreamSocket> stream_socket,const net::HostPortPair & host_and_port,const net::SSLConfig & ssl_config)258   std::unique_ptr<net::SSLClientSocket> CreateSSLClientSocket(
259       net::SSLClientContext* context,
260       std::unique_ptr<net::StreamSocket> stream_socket,
261       const net::HostPortPair& host_and_port,
262       const net::SSLConfig& ssl_config) override {
263     ADD_FAILURE() << "Called CreateSSLClientSocket()";
264     return nullptr;
265   }
CreateProxyClientSocket(std::unique_ptr<net::StreamSocket> stream_socket,const std::string & user_agent,const net::HostPortPair & endpoint,const net::ProxyServer & proxy_server,net::HttpAuthController * http_auth_controller,bool tunnel,bool using_spdy,net::NextProto negotiated_protocol,net::ProxyDelegate * proxy_delegate,const net::NetworkTrafficAnnotationTag & traffic_annotation)266   std::unique_ptr<net::ProxyClientSocket> CreateProxyClientSocket(
267       std::unique_ptr<net::StreamSocket> stream_socket,
268       const std::string& user_agent,
269       const net::HostPortPair& endpoint,
270       const net::ProxyServer& proxy_server,
271       net::HttpAuthController* http_auth_controller,
272       bool tunnel,
273       bool using_spdy,
274       net::NextProto negotiated_protocol,
275       net::ProxyDelegate* proxy_delegate,
276       const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
277     ADD_FAILURE() << "Called CreateProxyClientSocket()";
278     return nullptr;
279   }
280 
281  private:
282   std::vector<std::unique_ptr<MockUDPSocket>> udp_sockets_;
283 
284   DISALLOW_COPY_AND_ASSIGN(MockSocketFactory);
285 };
286 
287 // Tests myIpAddress() when there is a route to 8.8.8.8.
TEST(PacLibraryTest,PacMyIpAddress8888)288 TEST(PacLibraryTest, PacMyIpAddress8888) {
289   MockSocketFactory factory;
290   factory.AddUDPConnectSuccess("8.8.8.8", "192.168.1.1");
291 
292   auto result = PacMyIpAddressForTest(&factory, {});
293   ASSERT_EQ(1u, result.size());
294   EXPECT_EQ("192.168.1.1", result.front().ToString());
295 }
296 
297 // Tests myIpAddress() when there is no route to 8.8.8.8, but there is one to
298 // 2001:4860:4860::8888.
TEST(PacLibraryTest,PacMyIpAddress2001)299 TEST(PacLibraryTest, PacMyIpAddress2001) {
300   MockSocketFactory factory;
301   factory.AddUDPConnectFailure("8.8.8.8");
302   factory.AddUDPConnectSuccess("2001:4860:4860::8888", "2001::beef");
303 
304   net::AddressList dns_result;
305 
306   auto result = PacMyIpAddressForTest(&factory, dns_result);
307   ASSERT_EQ(1u, result.size());
308   EXPECT_EQ("2001::beef", result.front().ToString());
309 }
310 
311 // Tests myIpAddress() when there is no route to 8.8.8.8, no route to
312 // 2001:4860:4860::8888, however getaddrinfo(gethostname()) finds results. Most
313 // of those results are skipped over, and the IPv4 one is favored.
TEST(PacLibraryTest,PacMyIpAddressHostname)314 TEST(PacLibraryTest, PacMyIpAddressHostname) {
315   MockSocketFactory factory;
316   factory.AddUDPConnectFailure("8.8.8.8");
317   factory.AddUDPConnectFailure("2001:4860:4860::8888");
318 
319   net::AddressList dns_result = CreateAddressList({
320       "169.254.13.16",
321       "127.0.0.1",
322       "::1",
323       "fe89::beef",
324       "2001::f001",
325       "178.1.99.3",
326       "192.168.1.3",
327   });
328 
329   auto result = PacMyIpAddressForTest(&factory, dns_result);
330   ASSERT_EQ(1u, result.size());
331   EXPECT_EQ("178.1.99.3", result.front().ToString());
332 }
333 
334 // Tests myIpAddress() when there is no route to 8.8.8.8, no route to
335 // 2001:4860:4860::8888, however getaddrinfo(gethostname()) finds multiple IPv6
336 // results.
TEST(PacLibraryTest,PacMyIpAddressHostnameAllIPv6)337 TEST(PacLibraryTest, PacMyIpAddressHostnameAllIPv6) {
338   MockSocketFactory factory;
339   factory.AddUDPConnectFailure("8.8.8.8");
340   factory.AddUDPConnectFailure("2001:4860:4860::8888");
341 
342   net::AddressList dns_result =
343       CreateAddressList({"::1", "2001::f001", "2001::f00d", "169.254.0.6"});
344 
345   auto result = PacMyIpAddressForTest(&factory, dns_result);
346   ASSERT_EQ(1u, result.size());
347   EXPECT_EQ("2001::f001", result.front().ToString());
348 }
349 
350 // Tests myIpAddress() when there is no route to 8.8.8.8, no route to
351 // 2001:4860:4860::8888, no acceptable result in getaddrinfo(gethostname()),
352 // however there is a route for private address.
TEST(PacLibraryTest,PacMyIpAddressPrivateIPv4)353 TEST(PacLibraryTest, PacMyIpAddressPrivateIPv4) {
354   MockSocketFactory factory;
355   factory.AddUDPConnectFailure("8.8.8.8");
356   factory.AddUDPConnectFailure("2001:4860:4860::8888");
357 
358   net::AddressList dns_result = CreateAddressList({
359       "169.254.13.16",
360       "127.0.0.1",
361       "::1",
362       "fe89::beef",
363   });
364 
365   factory.AddUDPConnectSuccess("10.0.0.0", "127.0.0.1");
366   factory.AddUDPConnectFailure("172.16.0.0");
367   factory.AddUDPConnectSuccess("192.168.0.0", "63.31.9.8");
368 
369   auto result = PacMyIpAddressForTest(&factory, dns_result);
370   ASSERT_EQ(1u, result.size());
371   EXPECT_EQ("63.31.9.8", result.front().ToString());
372 }
373 
374 // Tests myIpAddress() when there is no route to 8.8.8.8, no route to
375 // 2001:4860:4860::8888, no acceptable result in getaddrinfo(gethostname()),
376 // however there is a route for private address.
TEST(PacLibraryTest,PacMyIpAddressPrivateIPv6)377 TEST(PacLibraryTest, PacMyIpAddressPrivateIPv6) {
378   MockSocketFactory factory;
379   factory.AddUDPConnectFailure("8.8.8.8");
380   factory.AddUDPConnectFailure("2001:4860:4860::8888");
381 
382   net::AddressList dns_result;
383 
384   factory.AddUDPConnectSuccess("10.0.0.0", "127.0.0.1");
385   factory.AddUDPConnectFailure("172.16.0.0");
386   factory.AddUDPConnectFailure("192.168.0.0");
387   factory.AddUDPConnectSuccess("FC00::", "2001::7777");
388 
389   auto result = PacMyIpAddressForTest(&factory, dns_result);
390   ASSERT_EQ(1u, result.size());
391   EXPECT_EQ("2001::7777", result.front().ToString());
392 }
393 
394 // Tests myIpAddress() when there are no routes, and getaddrinfo(gethostname())
395 // fails.
TEST(PacLibraryTest,PacMyIpAddressAllFail)396 TEST(PacLibraryTest, PacMyIpAddressAllFail) {
397   MockSocketFactory factory;
398   factory.AddUDPConnectFailure("8.8.8.8");
399   factory.AddUDPConnectFailure("2001:4860:4860::8888");
400 
401   net::AddressList dns_result;
402 
403   factory.AddUDPConnectFailure("10.0.0.0");
404   factory.AddUDPConnectFailure("172.16.0.0");
405   factory.AddUDPConnectFailure("192.168.0.0");
406   factory.AddUDPConnectFailure("FC00::");
407 
408   auto result = PacMyIpAddressForTest(&factory, dns_result);
409   EXPECT_EQ(0u, result.size());
410 }
411 
412 // Tests myIpAddress() when there are no routes, and
413 // getaddrinfo(gethostname()) only returns loopback.
TEST(PacLibraryTest,PacMyIpAddressAllFailOrLoopback)414 TEST(PacLibraryTest, PacMyIpAddressAllFailOrLoopback) {
415   MockSocketFactory factory;
416   factory.AddUDPConnectFailure("8.8.8.8");
417   factory.AddUDPConnectFailure("2001:4860:4860::8888");
418 
419   net::AddressList dns_result = CreateAddressList({"127.0.0.1", "::1"});
420 
421   factory.AddUDPConnectFailure("10.0.0.0");
422   factory.AddUDPConnectFailure("172.16.0.0");
423   factory.AddUDPConnectFailure("192.168.0.0");
424   factory.AddUDPConnectFailure("FC00::");
425 
426   auto result = PacMyIpAddressForTest(&factory, dns_result);
427   EXPECT_EQ(0u, result.size());
428 }
429 
430 // Tests myIpAddress() when there is only an IPv6 link-local address.
TEST(PacLibraryTest,PacMyIpAddressAllFailHasLinkLocal)431 TEST(PacLibraryTest, PacMyIpAddressAllFailHasLinkLocal) {
432   MockSocketFactory factory;
433   factory.AddUDPConnectFailure("8.8.8.8");
434   factory.AddUDPConnectFailure("2001:4860:4860::8888");
435 
436   net::AddressList dns_result =
437       CreateAddressList({"127.0.0.1", "::1", "fe81::8881"});
438 
439   factory.AddUDPConnectFailure("10.0.0.0");
440   factory.AddUDPConnectFailure("172.16.0.0");
441   factory.AddUDPConnectFailure("192.168.0.0");
442   factory.AddUDPConnectFailure("FC00::");
443 
444   auto result = PacMyIpAddressForTest(&factory, dns_result);
445   ASSERT_EQ(1u, result.size());
446   EXPECT_EQ("fe81::8881", result.front().ToString());
447 }
448 
449 // Tests myIpAddress() when there are only link-local addresses. The IPv4
450 // link-local address is favored.
TEST(PacLibraryTest,PacMyIpAddressAllFailHasLinkLocalFavorIPv4)451 TEST(PacLibraryTest, PacMyIpAddressAllFailHasLinkLocalFavorIPv4) {
452   MockSocketFactory factory;
453   factory.AddUDPConnectFailure("8.8.8.8");
454   factory.AddUDPConnectFailure("2001:4860:4860::8888");
455 
456   net::AddressList dns_result =
457       CreateAddressList({"127.0.0.1", "::1", "fe81::8881", "169.254.89.133"});
458 
459   factory.AddUDPConnectFailure("10.0.0.0");
460   factory.AddUDPConnectFailure("172.16.0.0");
461   factory.AddUDPConnectFailure("192.168.0.0");
462   factory.AddUDPConnectFailure("FC00::");
463 
464   auto result = PacMyIpAddressForTest(&factory, dns_result);
465   ASSERT_EQ(1u, result.size());
466   EXPECT_EQ("169.254.89.133", result.front().ToString());
467 }
468 
469 // Tests myIpAddressEx() when there is a route to 8.8.8.8 but not one to
470 // 2001:4860:4860::8888
TEST(PacLibraryTest,PacMyIpAddressEx8888)471 TEST(PacLibraryTest, PacMyIpAddressEx8888) {
472   MockSocketFactory factory;
473   factory.AddUDPConnectSuccess("8.8.8.8", "192.168.1.1");
474   factory.AddUDPConnectFailure("2001:4860:4860::8888");
475 
476   auto result = PacMyIpAddressExForTest(&factory, {});
477   ASSERT_EQ(1u, result.size());
478   EXPECT_EQ("192.168.1.1", result.front().ToString());
479 }
480 
481 // Tests myIpAddressEx() when there is a route to 2001:4860:4860::8888 but
482 // not 8.8.8.8.
TEST(PacLibraryTest,PacMyIpAddressEx2001)483 TEST(PacLibraryTest, PacMyIpAddressEx2001) {
484   MockSocketFactory factory;
485   factory.AddUDPConnectFailure("8.8.8.8");
486   factory.AddUDPConnectSuccess("2001:4860:4860::8888", "2001::3333");
487 
488   net::AddressList dns_result;
489 
490   auto result = PacMyIpAddressExForTest(&factory, dns_result);
491   ASSERT_EQ(1u, result.size());
492   EXPECT_EQ("2001::3333", result.front().ToString());
493 }
494 
495 // Tests myIpAddressEx() when there is a route to both 8.8.8.8 and
496 // 2001:4860:4860::8888.
TEST(PacLibraryTest,PacMyIpAddressEx8888And2001)497 TEST(PacLibraryTest, PacMyIpAddressEx8888And2001) {
498   MockSocketFactory factory;
499   factory.AddUDPConnectSuccess("8.8.8.8", "192.168.17.8");
500   factory.AddUDPConnectSuccess("2001:4860:4860::8888", "2001::8333");
501 
502   net::AddressList dns_result;
503 
504   auto result = PacMyIpAddressExForTest(&factory, dns_result);
505   ASSERT_EQ(2u, result.size());
506   EXPECT_EQ("192.168.17.8", result.front().ToString());
507   EXPECT_EQ("2001::8333", result.back().ToString());
508 }
509 
510 // Tests myIpAddressEx() when there is no route to 8.8.8.8, no route to
511 // 2001:4860:4860::8888, however getaddrinfo(gethostname()) finds results. Some
512 // of those results are skipped due to being link-local and loopback.
TEST(PacLibraryTest,PacMyIpAddressExHostname)513 TEST(PacLibraryTest, PacMyIpAddressExHostname) {
514   MockSocketFactory factory;
515   factory.AddUDPConnectFailure("8.8.8.8");
516   factory.AddUDPConnectFailure("2001:4860:4860::8888");
517 
518   net::AddressList dns_result = CreateAddressList({
519       "169.254.13.16",
520       "::1",
521       "fe89::beef",
522       "2001::bebe",
523       "178.1.99.3",
524       "127.0.0.1",
525       "192.168.1.3",
526   });
527 
528   auto result = PacMyIpAddressExForTest(&factory, dns_result);
529   ASSERT_EQ(3u, result.size());
530   EXPECT_EQ("2001::bebe", result[0].ToString());
531   EXPECT_EQ("178.1.99.3", result[1].ToString());
532   EXPECT_EQ("192.168.1.3", result[2].ToString());
533 }
534 
535 // Tests myIpAddressEx() when routes are found for private IP space.
TEST(PacLibraryTest,PacMyIpAddressExPrivateDuplicates)536 TEST(PacLibraryTest, PacMyIpAddressExPrivateDuplicates) {
537   MockSocketFactory factory;
538   factory.AddUDPConnectFailure("8.8.8.8");
539   factory.AddUDPConnectFailure("2001:4860:4860::8888");
540 
541   net::AddressList dns_result;
542 
543   factory.AddUDPConnectSuccess("10.0.0.0", "192.168.3.3");
544   factory.AddUDPConnectSuccess("172.16.0.0", "192.168.3.4");
545   factory.AddUDPConnectSuccess("192.168.0.0", "192.168.3.3");
546   factory.AddUDPConnectSuccess("FC00::", "2001::beef");
547 
548   auto result = PacMyIpAddressExForTest(&factory, dns_result);
549 
550   // Note that 192.168.3.3. was probed twice, but only added once to the final
551   // result.
552   ASSERT_EQ(3u, result.size());
553   EXPECT_EQ("192.168.3.3", result[0].ToString());
554   EXPECT_EQ("192.168.3.4", result[1].ToString());
555   EXPECT_EQ("2001::beef", result[2].ToString());
556 }
557 
558 // Tests myIpAddressEx() when there are no routes, and
559 // getaddrinfo(gethostname()) fails.
TEST(PacLibraryTest,PacMyIpAddressExAllFail)560 TEST(PacLibraryTest, PacMyIpAddressExAllFail) {
561   MockSocketFactory factory;
562   factory.AddUDPConnectFailure("8.8.8.8");
563   factory.AddUDPConnectFailure("2001:4860:4860::8888");
564 
565   net::AddressList dns_result;
566 
567   factory.AddUDPConnectFailure("10.0.0.0");
568   factory.AddUDPConnectFailure("172.16.0.0");
569   factory.AddUDPConnectFailure("192.168.0.0");
570   factory.AddUDPConnectFailure("FC00::");
571 
572   auto result = PacMyIpAddressExForTest(&factory, dns_result);
573   EXPECT_EQ(0u, result.size());
574 }
575 
576 // Tests myIpAddressEx() when there are only IPv6 link-local address.
TEST(PacLibraryTest,PacMyIpAddressExAllFailHasLinkLocal)577 TEST(PacLibraryTest, PacMyIpAddressExAllFailHasLinkLocal) {
578   MockSocketFactory factory;
579   factory.AddUDPConnectFailure("8.8.8.8");
580   factory.AddUDPConnectFailure("2001:4860:4860::8888");
581 
582   net::AddressList dns_result =
583       CreateAddressList({"127.0.0.1", "::1", "fe81::8881", "fe80::8899"});
584 
585   factory.AddUDPConnectFailure("10.0.0.0");
586   factory.AddUDPConnectFailure("172.16.0.0");
587   factory.AddUDPConnectFailure("192.168.0.0");
588   factory.AddUDPConnectSuccess("FC00::", "fe80::1");
589 
590   auto result = PacMyIpAddressExForTest(&factory, dns_result);
591   // There were four link-local addresses found, but only the first one is
592   // returned.
593   ASSERT_EQ(1u, result.size());
594   EXPECT_EQ("fe81::8881", result.front().ToString());
595 }
596 
597 // Tests myIpAddressEx() when there are only link-local addresses. The IPv4
598 // link-local address is favored.
TEST(PacLibraryTest,PacMyIpAddressExAllFailHasLinkLocalFavorIPv4)599 TEST(PacLibraryTest, PacMyIpAddressExAllFailHasLinkLocalFavorIPv4) {
600   MockSocketFactory factory;
601   factory.AddUDPConnectFailure("8.8.8.8");
602   factory.AddUDPConnectFailure("2001:4860:4860::8888");
603 
604   net::AddressList dns_result =
605       CreateAddressList({"127.0.0.1", "::1", "fe81::8881", "169.254.89.133"});
606 
607   factory.AddUDPConnectFailure("10.0.0.0");
608   factory.AddUDPConnectFailure("172.16.0.0");
609   factory.AddUDPConnectFailure("192.168.0.0");
610   factory.AddUDPConnectFailure("FC00::");
611 
612   auto result = PacMyIpAddressExForTest(&factory, dns_result);
613   ASSERT_EQ(1u, result.size());
614   EXPECT_EQ("169.254.89.133", result.front().ToString());
615 }
616 
617 // Tests myIpAddressEx() when there are no routes, and
618 // getaddrinfo(gethostname()) only returns loopback.
TEST(PacLibraryTest,PacMyIpAddressExAllFailOrLoopback)619 TEST(PacLibraryTest, PacMyIpAddressExAllFailOrLoopback) {
620   MockSocketFactory factory;
621   factory.AddUDPConnectFailure("8.8.8.8");
622   factory.AddUDPConnectFailure("2001:4860:4860::8888");
623 
624   net::AddressList dns_result = CreateAddressList({"127.0.0.1", "::1"});
625 
626   factory.AddUDPConnectFailure("10.0.0.0");
627   factory.AddUDPConnectFailure("172.16.0.0");
628   factory.AddUDPConnectFailure("192.168.0.0");
629   factory.AddUDPConnectFailure("FC00::");
630 
631   auto result = PacMyIpAddressExForTest(&factory, dns_result);
632   EXPECT_EQ(0u, result.size());
633 }
634 
635 }  // namespace
636 }  // namespace network
637