|  | // Copyright 2018 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/proxy_resolution/pac_library.h" | 
|  |  | 
|  | #include "net/base/address_list.h" | 
|  | #include "net/base/net_errors.h" | 
|  | #include "net/base/network_interfaces.h" | 
|  | #include "net/log/net_log_with_source.h" | 
|  | #include "net/socket/client_socket_factory.h" | 
|  | #include "net/socket/client_socket_handle.h" | 
|  | #include "net/socket/datagram_client_socket.h" | 
|  | #include "testing/gmock/include/gmock/gmock.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | namespace net { | 
|  | namespace { | 
|  |  | 
|  | // Helper for verifying whether the address list returned by myIpAddress() / | 
|  | // myIpAddressEx() looks correct. | 
|  | void VerifyActualMyIpAddresses(const IPAddressList& test_list) { | 
|  | // Enumerate all of the IP addresses for the system (skipping loopback and | 
|  | // link-local ones). This is used as a reference implementation to check | 
|  | // whether |test_list| (which was obtained using a different strategy) looks | 
|  | // correct. | 
|  | std::set<IPAddress> candidates; | 
|  | NetworkInterfaceList networks; | 
|  | GetNetworkList(&networks, EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES); | 
|  | for (const auto& network : networks) { | 
|  | if (network.address.IsLinkLocal() || network.address.IsLoopback()) | 
|  | continue; | 
|  | candidates.insert(network.address); | 
|  | } | 
|  |  | 
|  | // Ordinarily the machine running this test will have an IP address. However | 
|  | // for some bot configurations (notably Android) that may not be the case. | 
|  | EXPECT_EQ(candidates.empty(), test_list.empty()); | 
|  |  | 
|  | // |test_list| should be a subset of |candidates|. | 
|  | for (const auto& ip : test_list) | 
|  | EXPECT_EQ(1u, candidates.count(ip)); | 
|  | } | 
|  |  | 
|  | // Tests for PacMyIpAddress() and PacMyIpAddressEx(). | 
|  | TEST(PacLibraryTest, ActualPacMyIpAddress) { | 
|  | auto my_ip_addresses = PacMyIpAddress(); | 
|  |  | 
|  | VerifyActualMyIpAddresses(my_ip_addresses); | 
|  | } | 
|  |  | 
|  | TEST(PacLibraryTest, ActualPacMyIpAddressEx) { | 
|  | VerifyActualMyIpAddresses(PacMyIpAddressEx()); | 
|  | } | 
|  |  | 
|  | IPAddress CreateIPAddress(base::StringPiece literal) { | 
|  | IPAddress result; | 
|  | if (!result.AssignFromIPLiteral(literal)) { | 
|  | ADD_FAILURE() << "Failed parsing IP: " << literal; | 
|  | return IPAddress(); | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | AddressList CreateAddressList( | 
|  | const std::vector<base::StringPiece>& ip_literals) { | 
|  | AddressList result; | 
|  | for (const auto& ip : ip_literals) | 
|  | result.push_back(IPEndPoint(CreateIPAddress(ip), 8080)); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | class MockUDPSocket : public DatagramClientSocket { | 
|  | public: | 
|  | MockUDPSocket(const IPAddress& peer_ip, | 
|  | const IPAddress& local_ip, | 
|  | Error connect_error) | 
|  | : peer_ip_(peer_ip), local_ip_(local_ip), connect_error_(connect_error) {} | 
|  |  | 
|  | ~MockUDPSocket() override = default; | 
|  |  | 
|  | // Socket implementation. | 
|  | int Read(IOBuffer* buf, | 
|  | int buf_len, | 
|  | CompletionOnceCallback callback) override { | 
|  | ADD_FAILURE() << "Called Read()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  | int Write(IOBuffer* buf, | 
|  | int buf_len, | 
|  | CompletionOnceCallback callback, | 
|  | const NetworkTrafficAnnotationTag& traffic_annotation) override { | 
|  | ADD_FAILURE() << "Called Read()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  | int SetReceiveBufferSize(int32_t size) override { | 
|  | ADD_FAILURE() << "Called SetReceiveBufferSize()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  | int SetSendBufferSize(int32_t size) override { | 
|  | ADD_FAILURE() << "Called SetSendBufferSize()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  |  | 
|  | // DatagramSocket implementation. | 
|  | void Close() override { ADD_FAILURE() << "Called Close()"; } | 
|  | int GetPeerAddress(IPEndPoint* address) const override { | 
|  | ADD_FAILURE() << "Called GetPeerAddress()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  | int GetLocalAddress(IPEndPoint* address) const override { | 
|  | if (connect_error_ != OK) | 
|  | return connect_error_; | 
|  |  | 
|  | *address = IPEndPoint(local_ip_, 8080); | 
|  | return OK; | 
|  | } | 
|  | void UseNonBlockingIO() override { | 
|  | ADD_FAILURE() << "Called UseNonBlockingIO()"; | 
|  | } | 
|  | int SetDoNotFragment() override { | 
|  | ADD_FAILURE() << "Called SetDoNotFragment()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  | void SetMsgConfirm(bool confirm) override { | 
|  | ADD_FAILURE() << "Called SetMsgConfirm()"; | 
|  | } | 
|  | const NetLogWithSource& NetLog() const override { | 
|  | ADD_FAILURE() << "Called NetLog()"; | 
|  | return net_log_; | 
|  | } | 
|  |  | 
|  | // DatagramClientSocket implementation. | 
|  | int Connect(const IPEndPoint& address) override { | 
|  | EXPECT_EQ(peer_ip_.ToString(), address.address().ToString()); | 
|  | return connect_error_; | 
|  | } | 
|  | int ConnectUsingNetwork(NetworkChangeNotifier::NetworkHandle network, | 
|  | const IPEndPoint& address) override { | 
|  | ADD_FAILURE() << "Called ConnectUsingNetwork()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  | int ConnectUsingDefaultNetwork(const IPEndPoint& address) override { | 
|  | ADD_FAILURE() << "Called ConnectUsingDefaultNetwork()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  | NetworkChangeNotifier::NetworkHandle GetBoundNetwork() const override { | 
|  | ADD_FAILURE() << "Called GetBoundNetwork()"; | 
|  | return network_; | 
|  | } | 
|  | void ApplySocketTag(const SocketTag& tag) override { | 
|  | ADD_FAILURE() << "Called ApplySocketTag()"; | 
|  | } | 
|  | int WriteAsync( | 
|  | DatagramBuffers buffers, | 
|  | CompletionOnceCallback callback, | 
|  | const NetworkTrafficAnnotationTag& traffic_annotation) override { | 
|  | ADD_FAILURE() << "Called WriteAsync()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  | int WriteAsync( | 
|  | const char* buffer, | 
|  | size_t buf_len, | 
|  | CompletionOnceCallback callback, | 
|  | const NetworkTrafficAnnotationTag& traffic_annotation) override { | 
|  | ADD_FAILURE() << "Called WriteAsync()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  | DatagramBuffers GetUnwrittenBuffers() override { | 
|  | ADD_FAILURE() << "Called GetUnwrittenBuffers()"; | 
|  | return DatagramBuffers(); | 
|  | } | 
|  | void SetWriteAsyncEnabled(bool enabled) override { | 
|  | ADD_FAILURE() << "Called SetWriteAsyncEnabled()"; | 
|  | } | 
|  | void SetMaxPacketSize(size_t max_packet_size) override { | 
|  | ADD_FAILURE() << "Called SetWriteAsyncEnabled()"; | 
|  | } | 
|  | bool WriteAsyncEnabled() override { | 
|  | ADD_FAILURE() << "Called WriteAsyncEnabled()"; | 
|  | return false; | 
|  | } | 
|  | void SetWriteMultiCoreEnabled(bool enabled) override { | 
|  | ADD_FAILURE() << "Called SetWriteMultiCoreEnabled()"; | 
|  | } | 
|  | void SetSendmmsgEnabled(bool enabled) override { | 
|  | ADD_FAILURE() << "Called SetSendmmsgEnabled()"; | 
|  | } | 
|  | void SetWriteBatchingActive(bool active) override { | 
|  | ADD_FAILURE() << "Called SetWriteBatchingActive()"; | 
|  | } | 
|  | int SetMulticastInterface(uint32_t interface_index) override { | 
|  | ADD_FAILURE() << "Called SetMulticastInterface()"; | 
|  | return ERR_UNEXPECTED; | 
|  | } | 
|  |  | 
|  | private: | 
|  | NetLogWithSource net_log_; | 
|  | NetworkChangeNotifier::NetworkHandle network_; | 
|  |  | 
|  | IPAddress peer_ip_; | 
|  | IPAddress local_ip_; | 
|  | Error connect_error_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(MockUDPSocket); | 
|  | }; | 
|  |  | 
|  | class MockSocketFactory : public ClientSocketFactory { | 
|  | public: | 
|  | MockSocketFactory() = default; | 
|  |  | 
|  | void AddUDPConnectSuccess(base::StringPiece peer_ip_literal, | 
|  | base::StringPiece local_ip_literal) { | 
|  | auto peer_ip = CreateIPAddress(peer_ip_literal); | 
|  | auto local_ip = CreateIPAddress(local_ip_literal); | 
|  |  | 
|  | // The address family of local and peer IP must match. | 
|  | ASSERT_EQ(peer_ip.size(), local_ip.size()); | 
|  |  | 
|  | udp_sockets_.push_back(std::make_unique<MockUDPSocket>( | 
|  | peer_ip, local_ip, OK)); | 
|  | } | 
|  |  | 
|  | void AddUDPConnectFailure(base::StringPiece peer_ip) { | 
|  | udp_sockets_.push_back(std::make_unique<MockUDPSocket>( | 
|  | CreateIPAddress(peer_ip), IPAddress(), ERR_ADDRESS_UNREACHABLE)); | 
|  | } | 
|  |  | 
|  | ~MockSocketFactory() override { | 
|  | EXPECT_EQ(0u, udp_sockets_.size()) | 
|  | << "Not all of the mock sockets were consumed."; | 
|  | } | 
|  |  | 
|  | // ClientSocketFactory | 
|  | std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket( | 
|  | DatagramSocket::BindType bind_type, | 
|  | NetLog* net_log, | 
|  | const NetLogSource& source) override { | 
|  | if (udp_sockets_.empty()) { | 
|  | ADD_FAILURE() << "Not enough mock UDP sockets"; | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | auto result = std::move(udp_sockets_.front()); | 
|  | udp_sockets_.erase(udp_sockets_.begin()); | 
|  | return result; | 
|  | } | 
|  | std::unique_ptr<TransportClientSocket> CreateTransportClientSocket( | 
|  | const AddressList& addresses, | 
|  | std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher, | 
|  | NetLog* net_log, | 
|  | const NetLogSource& source) override { | 
|  | ADD_FAILURE() << "Called CreateTransportClientSocket()"; | 
|  | return nullptr; | 
|  | } | 
|  | std::unique_ptr<SSLClientSocket> CreateSSLClientSocket( | 
|  | SSLClientContext* context, | 
|  | std::unique_ptr<StreamSocket> stream_socket, | 
|  | const HostPortPair& host_and_port, | 
|  | const SSLConfig& ssl_config) override { | 
|  | ADD_FAILURE() << "Called CreateSSLClientSocket()"; | 
|  | return nullptr; | 
|  | } | 
|  | std::unique_ptr<ProxyClientSocket> CreateProxyClientSocket( | 
|  | std::unique_ptr<StreamSocket> stream_socket, | 
|  | const std::string& user_agent, | 
|  | const HostPortPair& endpoint, | 
|  | const ProxyServer& proxy_server, | 
|  | HttpAuthController* http_auth_controller, | 
|  | bool tunnel, | 
|  | bool using_spdy, | 
|  | NextProto negotiated_protocol, | 
|  | ProxyDelegate* proxy_delegate, | 
|  | const NetworkTrafficAnnotationTag& traffic_annotation) override { | 
|  | ADD_FAILURE() << "Called CreateProxyClientSocket()"; | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | private: | 
|  | std::vector<std::unique_ptr<MockUDPSocket>> udp_sockets_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(MockSocketFactory); | 
|  | }; | 
|  |  | 
|  | // Tests myIpAddress() when there is a route to 8.8.8.8. | 
|  | TEST(PacLibraryTest, PacMyIpAddress8888) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectSuccess("8.8.8.8", "192.168.1.1"); | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, {}); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("192.168.1.1", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddress() when there is no route to 8.8.8.8, but there is one to | 
|  | // 2001:4860:4860::8888. | 
|  | TEST(PacLibraryTest, PacMyIpAddress2001) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectSuccess("2001:4860:4860::8888", "2001::beef"); | 
|  |  | 
|  | AddressList dns_result; | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, dns_result); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("2001::beef", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddress() when there is no route to 8.8.8.8, no route to | 
|  | // 2001:4860:4860::8888, however getaddrinfo(gethostname()) finds results. Most | 
|  | // of those results are skipped over, and the IPv4 one is favored. | 
|  | TEST(PacLibraryTest, PacMyIpAddressHostname) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = CreateAddressList({ | 
|  | "169.254.13.16", "127.0.0.1", "::1", "fe89::beef", "2001::f001", | 
|  | "178.1.99.3", "192.168.1.3", | 
|  | }); | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, dns_result); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("178.1.99.3", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddress() when there is no route to 8.8.8.8, no route to | 
|  | // 2001:4860:4860::8888, however getaddrinfo(gethostname()) finds multiple IPv6 | 
|  | // results. | 
|  | TEST(PacLibraryTest, PacMyIpAddressHostnameAllIPv6) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = | 
|  | CreateAddressList({"::1", "2001::f001", "2001::f00d", "169.254.0.6"}); | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, dns_result); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("2001::f001", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddress() when there is no route to 8.8.8.8, no route to | 
|  | // 2001:4860:4860::8888, no acceptable result in getaddrinfo(gethostname()), | 
|  | // however there is a route for private address. | 
|  | TEST(PacLibraryTest, PacMyIpAddressPrivateIPv4) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = CreateAddressList({ | 
|  | "169.254.13.16", "127.0.0.1", "::1", "fe89::beef", | 
|  | }); | 
|  |  | 
|  | factory.AddUDPConnectSuccess("10.0.0.0", "127.0.0.1"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectSuccess("192.168.0.0", "63.31.9.8"); | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, dns_result); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("63.31.9.8", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddress() when there is no route to 8.8.8.8, no route to | 
|  | // 2001:4860:4860::8888, no acceptable result in getaddrinfo(gethostname()), | 
|  | // however there is a route for private address. | 
|  | TEST(PacLibraryTest, PacMyIpAddressPrivateIPv6) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result; | 
|  |  | 
|  | factory.AddUDPConnectSuccess("10.0.0.0", "127.0.0.1"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectFailure("192.168.0.0"); | 
|  | factory.AddUDPConnectSuccess("FC00::", "2001::7777"); | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, dns_result); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("2001::7777", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddress() when there are no routes, and getaddrinfo(gethostname()) | 
|  | // fails. | 
|  | TEST(PacLibraryTest, PacMyIpAddressAllFail) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result; | 
|  |  | 
|  | factory.AddUDPConnectFailure("10.0.0.0"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectFailure("192.168.0.0"); | 
|  | factory.AddUDPConnectFailure("FC00::"); | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, dns_result); | 
|  | EXPECT_EQ(0u, result.size()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddress() when there are no routes, and | 
|  | // getaddrinfo(gethostname()) only returns loopback. | 
|  | TEST(PacLibraryTest, PacMyIpAddressAllFailOrLoopback) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = CreateAddressList({"127.0.0.1", "::1"}); | 
|  |  | 
|  | factory.AddUDPConnectFailure("10.0.0.0"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectFailure("192.168.0.0"); | 
|  | factory.AddUDPConnectFailure("FC00::"); | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, dns_result); | 
|  | EXPECT_EQ(0u, result.size()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddress() when there is only an IPv6 link-local address. | 
|  | TEST(PacLibraryTest, PacMyIpAddressAllFailHasLinkLocal) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = | 
|  | CreateAddressList({"127.0.0.1", "::1", "fe81::8881"}); | 
|  |  | 
|  | factory.AddUDPConnectFailure("10.0.0.0"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectFailure("192.168.0.0"); | 
|  | factory.AddUDPConnectFailure("FC00::"); | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, dns_result); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("fe81::8881", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddress() when there are only link-local addresses. The IPv4 | 
|  | // link-local address is favored. | 
|  | TEST(PacLibraryTest, PacMyIpAddressAllFailHasLinkLocalFavorIPv4) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = | 
|  | CreateAddressList({"127.0.0.1", "::1", "fe81::8881", "169.254.89.133"}); | 
|  |  | 
|  | factory.AddUDPConnectFailure("10.0.0.0"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectFailure("192.168.0.0"); | 
|  | factory.AddUDPConnectFailure("FC00::"); | 
|  |  | 
|  | auto result = PacMyIpAddressForTest(&factory, dns_result); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("169.254.89.133", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddressEx() when there is a route to 8.8.8.8 but not one to | 
|  | // 2001:4860:4860::8888 | 
|  | TEST(PacLibraryTest, PacMyIpAddressEx8888) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectSuccess("8.8.8.8", "192.168.1.1"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | auto result = PacMyIpAddressExForTest(&factory, {}); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("192.168.1.1", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddressEx() when there is a route to 2001:4860:4860::8888 but | 
|  | // not 8.8.8.8. | 
|  | TEST(PacLibraryTest, PacMyIpAddressEx2001) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectSuccess("2001:4860:4860::8888", "2001::3333"); | 
|  |  | 
|  | AddressList dns_result; | 
|  |  | 
|  | auto result = PacMyIpAddressExForTest(&factory, dns_result); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("2001::3333", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddressEx() when there is a route to both 8.8.8.8 and | 
|  | // 2001:4860:4860::8888. | 
|  | TEST(PacLibraryTest, PacMyIpAddressEx8888And2001) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectSuccess("8.8.8.8", "192.168.17.8"); | 
|  | factory.AddUDPConnectSuccess("2001:4860:4860::8888", "2001::8333"); | 
|  |  | 
|  | AddressList dns_result; | 
|  |  | 
|  | auto result = PacMyIpAddressExForTest(&factory, dns_result); | 
|  | ASSERT_EQ(2u, result.size()); | 
|  | EXPECT_EQ("192.168.17.8", result.front().ToString()); | 
|  | EXPECT_EQ("2001::8333", result.back().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddressEx() when there is no route to 8.8.8.8, no route to | 
|  | // 2001:4860:4860::8888, however getaddrinfo(gethostname()) finds results. Some | 
|  | // of those results are skipped due to being link-local and loopback. | 
|  | TEST(PacLibraryTest, PacMyIpAddressExHostname) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = CreateAddressList({ | 
|  | "169.254.13.16", "::1", "fe89::beef", "2001::bebe", "178.1.99.3", | 
|  | "127.0.0.1", "192.168.1.3", | 
|  | }); | 
|  |  | 
|  | auto result = PacMyIpAddressExForTest(&factory, dns_result); | 
|  | ASSERT_EQ(3u, result.size()); | 
|  | EXPECT_EQ("2001::bebe", result[0].ToString()); | 
|  | EXPECT_EQ("178.1.99.3", result[1].ToString()); | 
|  | EXPECT_EQ("192.168.1.3", result[2].ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddressEx() when routes are found for private IP space. | 
|  | TEST(PacLibraryTest, PacMyIpAddressExPrivateDuplicates) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result; | 
|  |  | 
|  | factory.AddUDPConnectSuccess("10.0.0.0", "192.168.3.3"); | 
|  | factory.AddUDPConnectSuccess("172.16.0.0", "192.168.3.4"); | 
|  | factory.AddUDPConnectSuccess("192.168.0.0", "192.168.3.3"); | 
|  | factory.AddUDPConnectSuccess("FC00::", "2001::beef"); | 
|  |  | 
|  | auto result = PacMyIpAddressExForTest(&factory, dns_result); | 
|  |  | 
|  | // Note that 192.168.3.3. was probed twice, but only added once to the final | 
|  | // result. | 
|  | ASSERT_EQ(3u, result.size()); | 
|  | EXPECT_EQ("192.168.3.3", result[0].ToString()); | 
|  | EXPECT_EQ("192.168.3.4", result[1].ToString()); | 
|  | EXPECT_EQ("2001::beef", result[2].ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddressEx() when there are no routes, and | 
|  | // getaddrinfo(gethostname()) fails. | 
|  | TEST(PacLibraryTest, PacMyIpAddressExAllFail) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result; | 
|  |  | 
|  | factory.AddUDPConnectFailure("10.0.0.0"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectFailure("192.168.0.0"); | 
|  | factory.AddUDPConnectFailure("FC00::"); | 
|  |  | 
|  | auto result = PacMyIpAddressExForTest(&factory, dns_result); | 
|  | EXPECT_EQ(0u, result.size()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddressEx() when there are only IPv6 link-local address. | 
|  | TEST(PacLibraryTest, PacMyIpAddressExAllFailHasLinkLocal) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = | 
|  | CreateAddressList({"127.0.0.1", "::1", "fe81::8881", "fe80::8899"}); | 
|  |  | 
|  | factory.AddUDPConnectFailure("10.0.0.0"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectFailure("192.168.0.0"); | 
|  | factory.AddUDPConnectSuccess("FC00::", "fe80::1"); | 
|  |  | 
|  | auto result = PacMyIpAddressExForTest(&factory, dns_result); | 
|  | // There were four link-local addresses found, but only the first one is | 
|  | // returned. | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("fe81::8881", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddressEx() when there are only link-local addresses. The IPv4 | 
|  | // link-local address is favored. | 
|  | TEST(PacLibraryTest, PacMyIpAddressExAllFailHasLinkLocalFavorIPv4) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = | 
|  | CreateAddressList({"127.0.0.1", "::1", "fe81::8881", "169.254.89.133"}); | 
|  |  | 
|  | factory.AddUDPConnectFailure("10.0.0.0"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectFailure("192.168.0.0"); | 
|  | factory.AddUDPConnectFailure("FC00::"); | 
|  |  | 
|  | auto result = PacMyIpAddressExForTest(&factory, dns_result); | 
|  | ASSERT_EQ(1u, result.size()); | 
|  | EXPECT_EQ("169.254.89.133", result.front().ToString()); | 
|  | } | 
|  |  | 
|  | // Tests myIpAddressEx() when there are no routes, and | 
|  | // getaddrinfo(gethostname()) only returns loopback. | 
|  | TEST(PacLibraryTest, PacMyIpAddressExAllFailOrLoopback) { | 
|  | MockSocketFactory factory; | 
|  | factory.AddUDPConnectFailure("8.8.8.8"); | 
|  | factory.AddUDPConnectFailure("2001:4860:4860::8888"); | 
|  |  | 
|  | AddressList dns_result = CreateAddressList({"127.0.0.1", "::1"}); | 
|  |  | 
|  | factory.AddUDPConnectFailure("10.0.0.0"); | 
|  | factory.AddUDPConnectFailure("172.16.0.0"); | 
|  | factory.AddUDPConnectFailure("192.168.0.0"); | 
|  | factory.AddUDPConnectFailure("FC00::"); | 
|  |  | 
|  | auto result = PacMyIpAddressExForTest(&factory, dns_result); | 
|  | EXPECT_EQ(0u, result.size()); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  | }  // namespace net |