| // |
| // Copyright (C) 2015 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "shill/connection_diagnostics.h" |
| |
| #include <net/if_arp.h> |
| |
| #include <gtest/gtest.h> |
| |
| #include "shill/arp_client.h" |
| #include "shill/arp_client_test_helper.h" |
| #include "shill/icmp_session.h" |
| #include "shill/mock_arp_client.h" |
| #include "shill/mock_connection.h" |
| #include "shill/mock_control.h" |
| #include "shill/mock_device_info.h" |
| #include "shill/mock_dns_client.h" |
| #include "shill/mock_dns_client_factory.h" |
| #include "shill/mock_event_dispatcher.h" |
| #include "shill/mock_icmp_session.h" |
| #include "shill/mock_icmp_session_factory.h" |
| #include "shill/mock_manager.h" |
| #include "shill/mock_metrics.h" |
| #include "shill/mock_portal_detector.h" |
| #include "shill/mock_routing_table.h" |
| #include "shill/net/mock_rtnl_handler.h" |
| |
| using base::Bind; |
| using base::Callback; |
| using base::Unretained; |
| using std::string; |
| using std::vector; |
| using testing::_; |
| using testing::NiceMock; |
| using testing::Return; |
| using testing::ReturnRef; |
| using testing::SetArgumentPointee; |
| using testing::Test; |
| |
| namespace { |
| const char kInterfaceName[] = "int0"; |
| const char kDNSServer0[] = "8.8.8.8"; |
| const char kDNSServer1[] = "8.8.4.4"; |
| const char kURL[] = "http://www.gstatic.com/generate_204"; |
| const char kLocalMacAddressASCIIString[] = "123456"; |
| const char kArpReplySenderMacAddressASCIIString[] = "345678"; |
| const char* kDNSServers[] = {kDNSServer0, kDNSServer1}; |
| const shill::IPAddress kIPv4LocalAddress("100.200.43.22"); |
| const shill::IPAddress kIPv4ServerAddress("8.8.8.8"); |
| const shill::IPAddress kIPv6ServerAddress("fe80::1aa9:5ff:7ebf:14c5"); |
| const shill::IPAddress kIPv4GatewayAddress("192.168.1.1"); |
| const shill::IPAddress kIPv6GatewayAddress("fee2::11b2:53f:13be:125e"); |
| const vector<base::TimeDelta> kEmptyResult; |
| const vector<base::TimeDelta> kNonEmptyResult{ |
| base::TimeDelta::FromMilliseconds(10)}; |
| } // namespace |
| |
| namespace shill { |
| |
| MATCHER_P(IsSameIPAddress, ip_addr, "") { |
| return arg.Equals(ip_addr); |
| } |
| |
| MATCHER_P(IsEventList, expected_events, "") { |
| // Match on type, phase, and result, but not message. |
| if (arg.size() != expected_events.size()) { |
| return false; |
| } |
| for (size_t i = 0; i < expected_events.size(); ++i) { |
| if (expected_events[i].type != arg[i].type || |
| expected_events[i].phase != arg[i].phase || |
| expected_events[i].result != arg[i].result) { |
| *result_listener << "\n=== Mismatch found on expected event index " << i |
| << " ==="; |
| *result_listener << "\nExpected: " |
| << ConnectionDiagnostics::EventToString( |
| expected_events[i]); |
| *result_listener << "\n Actual: " |
| << ConnectionDiagnostics::EventToString(arg[i]); |
| *result_listener << "\nExpected connection diagnostics events:"; |
| for (const auto& expected_event : expected_events) { |
| *result_listener << "\n" << ConnectionDiagnostics::EventToString( |
| expected_event); |
| } |
| *result_listener << "\nActual connection diagnostics events:"; |
| for (const auto& actual_event : expected_events) { |
| *result_listener << "\n" |
| << ConnectionDiagnostics::EventToString(actual_event); |
| } |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| MATCHER_P4(IsArpRequest, local_ip, remote_ip, local_mac, remote_mac, "") { |
| if (local_ip.Equals(arg.local_ip_address()) && |
| remote_ip.Equals(arg.remote_ip_address()) && |
| local_mac.Equals(arg.local_mac_address()) && |
| remote_mac.Equals(arg.remote_mac_address())) { |
| return true; |
| } |
| |
| if (!local_ip.Equals(arg.local_ip_address())) { |
| *result_listener << "Local IP '" << arg.local_ip_address().ToString() |
| << "' (expected '" << local_ip.ToString() << "')."; |
| } |
| |
| if (!remote_ip.Equals(arg.remote_ip_address())) { |
| *result_listener << "Remote IP '" << arg.remote_ip_address().ToString() |
| << "' (expected '" << remote_ip.ToString() << "')."; |
| } |
| |
| if (!local_mac.Equals(arg.local_mac_address())) { |
| *result_listener << "Local MAC '" << arg.local_mac_address().HexEncode() |
| << "' (expected " << local_mac.HexEncode() << ")'."; |
| } |
| |
| if (!remote_mac.Equals(arg.remote_mac_address())) { |
| *result_listener << "Remote MAC '" << arg.remote_mac_address().HexEncode() |
| << "' (expected " << remote_mac.HexEncode() << ")'."; |
| } |
| |
| return false; |
| } |
| |
| class ConnectionDiagnosticsTest : public Test { |
| public: |
| ConnectionDiagnosticsTest() |
| : interface_name_(kInterfaceName), |
| dns_servers_(kDNSServers, kDNSServers + 2), |
| local_ip_address_(kIPv4LocalAddress), |
| gateway_ipv4_address_(kIPv4GatewayAddress), |
| gateway_ipv6_address_(kIPv6GatewayAddress), |
| local_mac_address_(string(kLocalMacAddressASCIIString), false), |
| metrics_(&dispatcher_), |
| manager_(&control_, &dispatcher_, &metrics_), |
| device_info_(&control_, &dispatcher_, &metrics_, &manager_), |
| connection_(new NiceMock<MockConnection>(&device_info_)), |
| connection_diagnostics_(connection_, &dispatcher_, &metrics_, |
| &device_info_, |
| callback_target_.result_callback()), |
| portal_detector_(new NiceMock<MockPortalDetector>(connection_)) {} |
| virtual ~ConnectionDiagnosticsTest() {} |
| |
| virtual void SetUp() { |
| ASSERT_EQ(IPAddress::kFamilyIPv4, kIPv4LocalAddress.family()); |
| ASSERT_EQ(IPAddress::kFamilyIPv4, kIPv4ServerAddress.family()); |
| ASSERT_EQ(IPAddress::kFamilyIPv4, kIPv4GatewayAddress.family()); |
| ASSERT_EQ(IPAddress::kFamilyIPv6, kIPv6ServerAddress.family()); |
| ASSERT_EQ(IPAddress::kFamilyIPv6, kIPv6GatewayAddress.family()); |
| |
| arp_client_ = new NiceMock<MockArpClient>(); |
| client_test_helper_.reset(new ArpClientTestHelper(arp_client_)); |
| icmp_session_ = new NiceMock<MockIcmpSession>(&dispatcher_); |
| connection_diagnostics_.arp_client_.reset(arp_client_); // Passes ownership |
| connection_diagnostics_.icmp_session_.reset( |
| icmp_session_); // Passes ownership |
| connection_diagnostics_.portal_detector_.reset( |
| portal_detector_); // Passes ownership |
| connection_diagnostics_.routing_table_ = &routing_table_; |
| connection_diagnostics_.rtnl_handler_ = &rtnl_handler_; |
| ON_CALL(*connection_.get(), interface_name()) |
| .WillByDefault(ReturnRef(interface_name_)); |
| ON_CALL(*connection_.get(), dns_servers()) |
| .WillByDefault(ReturnRef(dns_servers_)); |
| ON_CALL(*connection_.get(), gateway()) |
| .WillByDefault(ReturnRef(gateway_ipv4_address_)); |
| ON_CALL(*connection_.get(), local()) |
| .WillByDefault(ReturnRef(local_ip_address_)); |
| connection_diagnostics_.dns_client_factory_ = |
| MockDNSClientFactory::GetInstance(); |
| connection_diagnostics_.icmp_session_factory_ = |
| MockIcmpSessionFactory::GetInstance(); |
| } |
| |
| virtual void TearDown() {} |
| |
| protected: |
| class CallbackTarget { |
| public: |
| CallbackTarget() |
| : result_callback_( |
| Bind(&CallbackTarget::ResultCallback, Unretained(this))) {} |
| |
| MOCK_METHOD2(ResultCallback, |
| void(const string&, |
| const vector<ConnectionDiagnostics::Event>&)); |
| |
| Callback<void(const string&, const vector<ConnectionDiagnostics::Event>&)>& |
| result_callback() { |
| return result_callback_; |
| } |
| |
| private: |
| Callback<void(const string&, const vector<ConnectionDiagnostics::Event>&)> |
| result_callback_; |
| }; |
| |
| CallbackTarget& callback_target() { |
| return callback_target_; |
| } |
| |
| void UseIPv6Gateway() { |
| EXPECT_CALL(*connection_.get(), gateway()) |
| .WillRepeatedly(ReturnRef(gateway_ipv6_address_)); |
| } |
| |
| void AddExpectedEvent(ConnectionDiagnostics::Type type, |
| ConnectionDiagnostics::Phase phase, |
| ConnectionDiagnostics::Result result) { |
| expected_events_.push_back( |
| ConnectionDiagnostics::Event(type, phase, result, "")); |
| } |
| |
| void AddActualEvent(ConnectionDiagnostics::Type type, |
| ConnectionDiagnostics::Phase phase, |
| ConnectionDiagnostics::Result result) { |
| connection_diagnostics_.diagnostic_events_.push_back( |
| ConnectionDiagnostics::Event(type, phase, result, "")); |
| } |
| |
| bool DoesPreviousEventMatch(ConnectionDiagnostics::Type type, |
| ConnectionDiagnostics::Phase phase, |
| ConnectionDiagnostics::Result result, |
| size_t num_events_ago) { |
| return connection_diagnostics_.DoesPreviousEventMatch(type, phase, result, |
| num_events_ago); |
| } |
| |
| // This direct call to ConnectionDiagnostics::Start does not mock the |
| // return |
| // value of MockPortalDetector::CreatePortalDetector, so this will crash |
| // the |
| // test if PortalDetector::Start is actually called. Use only for testing |
| // bad input to ConnectionDiagnostics::Start. |
| bool Start(const string& url_string) { |
| return connection_diagnostics_.Start(url_string); |
| } |
| |
| void VerifyStopped() { |
| EXPECT_FALSE(connection_diagnostics_.running()); |
| EXPECT_EQ(0, connection_diagnostics_.num_dns_attempts_); |
| EXPECT_TRUE(connection_diagnostics_.diagnostic_events_.empty()); |
| EXPECT_FALSE(connection_diagnostics_.dns_client_.get()); |
| EXPECT_FALSE(connection_diagnostics_.arp_client_->IsStarted()); |
| EXPECT_FALSE(connection_diagnostics_.icmp_session_->IsStarted()); |
| EXPECT_FALSE(connection_diagnostics_.portal_detector_.get()); |
| EXPECT_FALSE(connection_diagnostics_.receive_response_handler_.get()); |
| EXPECT_FALSE(connection_diagnostics_.neighbor_msg_listener_.get()); |
| EXPECT_TRUE( |
| connection_diagnostics_.id_to_pending_dns_server_icmp_session_.empty()); |
| EXPECT_FALSE(connection_diagnostics_.target_url_.get()); |
| EXPECT_TRUE(connection_diagnostics_.route_query_callback_.IsCancelled()); |
| EXPECT_TRUE( |
| connection_diagnostics_.route_query_timeout_callback_.IsCancelled()); |
| EXPECT_TRUE( |
| connection_diagnostics_.arp_reply_timeout_callback_.IsCancelled()); |
| EXPECT_TRUE(connection_diagnostics_.neighbor_request_timeout_callback_ |
| .IsCancelled()); |
| } |
| |
| void ExpectIcmpSessionStop() { |
| EXPECT_CALL(*icmp_session_, Stop()); |
| } |
| |
| void ExpectPortalDetectionStartSuccess(const string& url_string) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypePortalDetection, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess); |
| EXPECT_CALL(*portal_detector_, Start(url_string)).WillOnce(Return(true)); |
| EXPECT_FALSE(connection_diagnostics_.running()); |
| EXPECT_TRUE(connection_diagnostics_.diagnostic_events_.empty()); |
| EXPECT_TRUE(Start(url_string)); |
| EXPECT_TRUE(connection_diagnostics_.running()); |
| } |
| |
| void ExpectPortalDetectionEndContentPhaseSuccess() { |
| ExpectPortalDetectionEnd( |
| ConnectionDiagnostics::kPhasePortalDetectionEndContent, |
| ConnectionDiagnostics::kResultSuccess, |
| ConnectivityTrial::kPhaseContent, |
| ConnectivityTrial::kStatusSuccess); |
| } |
| |
| void ExpectPortalDetectionEndContentPhaseFailure() { |
| ExpectPortalDetectionEnd( |
| ConnectionDiagnostics::kPhasePortalDetectionEndContent, |
| ConnectionDiagnostics::kResultFailure, |
| ConnectivityTrial::kPhaseContent, |
| ConnectivityTrial::kStatusFailure); |
| } |
| |
| void ExpectPortalDetectionEndDNSPhaseFailure() { |
| ExpectPortalDetectionEnd(ConnectionDiagnostics::kPhasePortalDetectionEndDNS, |
| ConnectionDiagnostics::kResultFailure, |
| ConnectivityTrial::kPhaseDNS, |
| ConnectivityTrial::kStatusFailure); |
| } |
| |
| void ExpectPortalDetectionEndDNSPhaseTimeout() { |
| ExpectPortalDetectionEnd(ConnectionDiagnostics::kPhasePortalDetectionEndDNS, |
| ConnectionDiagnostics::kResultTimeout, |
| ConnectivityTrial::kPhaseDNS, |
| ConnectivityTrial::kStatusTimeout); |
| } |
| |
| void ExpectPortalDetectionEndHTTPPhaseFailure() { |
| ExpectPortalDetectionEnd( |
| ConnectionDiagnostics::kPhasePortalDetectionEndOther, |
| ConnectionDiagnostics::kResultFailure, |
| ConnectivityTrial::kPhaseHTTP, |
| ConnectivityTrial::kStatusFailure); |
| } |
| |
| void ExpectPingDNSServersStartSuccess() { |
| ExpectPingDNSSeversStart(true, ""); |
| } |
| |
| void ExpectPingDNSSeversStartFailureAllAddressesInvalid() { |
| ExpectPingDNSSeversStart(false, |
| ConnectionDiagnostics::kIssueDNSServersInvalid); |
| } |
| |
| void ExpectPingDNSSeversStartFailureAllIcmpSessionsFailed() { |
| ExpectPingDNSSeversStart(false, ConnectionDiagnostics::kIssueInternalError); |
| } |
| |
| void ExpectPingDNSServersEndSuccessRetriesLeft() { |
| ExpectPingDNSServersEndSuccess(true); |
| } |
| |
| void ExpectPingDNSServersEndSuccessNoRetriesLeft() { |
| ExpectPingDNSServersEndSuccess(false); |
| } |
| |
| void ExpectPingDNSServersEndFailure() { |
| AddExpectedEvent(ConnectionDiagnostics::kTypePingDNSServers, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultFailure); |
| // Post task to find DNS server route only after all (i.e. 2) pings are |
| // done. |
| connection_diagnostics_.OnPingDNSServerComplete(0, kEmptyResult); |
| EXPECT_CALL(dispatcher_, PostTask(_)); |
| connection_diagnostics_.OnPingDNSServerComplete(1, kEmptyResult); |
| } |
| |
| void ExpectResolveTargetServerIPAddressStartSuccess( |
| IPAddress::Family family) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeResolveTargetServerIP, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess); |
| ASSERT_FALSE(family == IPAddress::kFamilyUnknown); |
| |
| dns_client_ = new NiceMock<MockDNSClient>(); |
| EXPECT_CALL(*connection_.get(), IsIPv6()) |
| .WillOnce(Return(family == IPAddress::kFamilyIPv6)); |
| EXPECT_CALL( |
| *MockDNSClientFactory::GetInstance(), |
| CreateDNSClient(family, kInterfaceName, dns_servers_, |
| ConnectionDiagnostics::kDNSTimeoutSeconds * 1000, |
| &dispatcher_, _)) |
| .WillOnce(Return(dns_client_)); // Passes ownership |
| EXPECT_CALL(*dns_client_, |
| Start(connection_diagnostics_.target_url_->host(), _)) |
| .WillOnce(Return(true)); |
| connection_diagnostics_.ResolveTargetServerIPAddress(dns_servers_); |
| } |
| |
| void ExpectResolveTargetServerIPAddressEndSuccess( |
| const IPAddress& resolved_address) { |
| ExpectResolveTargetServerIPAddressEnd(ConnectionDiagnostics::kResultSuccess, |
| resolved_address); |
| } |
| |
| void ExpectResolveTargetServerIPAddressEndTimeout() { |
| ExpectResolveTargetServerIPAddressEnd(ConnectionDiagnostics::kResultTimeout, |
| IPAddress(IPAddress::kFamilyIPv4)); |
| } |
| |
| void ExpectResolveTargetServerIPAddressEndFailure() { |
| ExpectResolveTargetServerIPAddressEnd(ConnectionDiagnostics::kResultFailure, |
| IPAddress(IPAddress::kFamilyIPv4)); |
| } |
| |
| void ExpectPingHostStartSuccess(ConnectionDiagnostics::Type ping_event_type, |
| const IPAddress& address) { |
| AddExpectedEvent(ping_event_type, ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess); |
| EXPECT_CALL(*icmp_session_, Start(IsSameIPAddress(address), _)) |
| .WillOnce(Return(true)); |
| connection_diagnostics_.PingHost(address); |
| } |
| |
| void ExpectPingHostStartFailure(ConnectionDiagnostics::Type ping_event_type, |
| const IPAddress& address) { |
| AddExpectedEvent(ping_event_type, ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultFailure); |
| EXPECT_CALL(*icmp_session_, Start(IsSameIPAddress(address), _)) |
| .WillOnce(Return(false)); |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue( |
| ConnectionDiagnostics::kIssueInternalError)); |
| EXPECT_CALL(callback_target(), |
| ResultCallback(ConnectionDiagnostics::kIssueInternalError, |
| IsEventList(expected_events_))); |
| connection_diagnostics_.PingHost(address); |
| } |
| |
| void ExpectPingHostEndSuccess(ConnectionDiagnostics::Type ping_event_type, |
| const IPAddress& address) { |
| AddExpectedEvent(ping_event_type, ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultSuccess); |
| const string& issue = |
| ping_event_type == ConnectionDiagnostics::kTypePingGateway |
| ? ConnectionDiagnostics::kIssueGatewayUpstream |
| : ConnectionDiagnostics::kIssueHTTPBrokenPortal; |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(issue)); |
| EXPECT_CALL(callback_target(), |
| ResultCallback(issue, IsEventList(expected_events_))); |
| connection_diagnostics_.OnPingHostComplete(ping_event_type, address, |
| kNonEmptyResult); |
| } |
| |
| void ExpectPingHostEndFailure(ConnectionDiagnostics::Type ping_event_type, |
| const IPAddress& address) { |
| AddExpectedEvent(ping_event_type, ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultFailure); |
| // Next action is either to find a route to the target web server, find an |
| // ARP entry for the IPv4 gateway, or find a neighbor table entry for the |
| // IPv6 gateway. |
| EXPECT_CALL(dispatcher_, PostTask(_)); |
| connection_diagnostics_.OnPingHostComplete(ping_event_type, address, |
| kEmptyResult); |
| } |
| |
| void ExpectFindRouteToHostStartSuccess(const IPAddress& address) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeFindRoute, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess); |
| EXPECT_CALL(routing_table_, |
| RequestRouteToHost(IsSameIPAddress(address), |
| connection_->interface_index(), _, _, |
| connection_->table_id())) |
| .WillOnce(Return(true)); |
| EXPECT_CALL( |
| dispatcher_, |
| PostDelayedTask( |
| _, ConnectionDiagnostics::kRouteQueryTimeoutSeconds * 1000)); |
| connection_diagnostics_.FindRouteToHost(address); |
| EXPECT_FALSE( |
| connection_diagnostics_.route_query_timeout_callback_.IsCancelled()); |
| } |
| |
| void ExpectFindRouteToHostEndSuccess(const IPAddress& address_queried, |
| bool is_local_address) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeFindRoute, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultSuccess); |
| |
| IPAddress gateway(IPAddress::kFamilyIPv4); |
| if (is_local_address) { |
| gateway.SetAddressToDefault(); |
| } else { |
| // Could be an IPv6 address, but we instrument this later with the |
| // argument passed to ExpectPingHostStartSuccess. |
| gateway = gateway_ipv4_address_; |
| } |
| |
| // Next action is either to ping the gateway, find an ARP table entry for |
| // the local IPv4 web server, or find a neighbor table entry for the local |
| // IPv6 web server. |
| EXPECT_CALL(dispatcher_, PostTask(_)); |
| RoutingTableEntry entry( |
| address_queried, IPAddress(address_queried.family()), gateway, 0, |
| RT_SCOPE_UNIVERSE, true, connection_->table_id(), -1); |
| connection_diagnostics_.OnRouteQueryResponse(connection_->interface_index(), |
| entry); |
| } |
| |
| void ExpectFindRouteToHostEndFailure() { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeFindRoute, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultFailure); |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue( |
| ConnectionDiagnostics::kIssueRouting)); |
| EXPECT_CALL(callback_target(), |
| ResultCallback(ConnectionDiagnostics::kIssueRouting, |
| IsEventList(expected_events_))); |
| connection_diagnostics_.OnRouteQueryTimeout(); |
| } |
| |
| void ExpectArpTableLookupStartSuccessEndSuccess(const IPAddress& address, |
| bool is_gateway) { |
| ExpectArpTableLookup(address, true, is_gateway); |
| } |
| |
| void ExpectArpTableLookupStartSuccessEndFailure(const IPAddress& address) { |
| ExpectArpTableLookup(address, false, false); |
| } |
| |
| void ExpectNeighborTableLookupStartSuccess(const IPAddress& address) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeNeighborTableLookup, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess); |
| EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestNeighbor)); |
| EXPECT_CALL( |
| dispatcher_, |
| PostDelayedTask( |
| _, |
| ConnectionDiagnostics::kNeighborTableRequestTimeoutSeconds * 1000)); |
| connection_diagnostics_.FindNeighborTableEntry(address); |
| } |
| |
| void ExpectNeighborTableLookupEndSuccess(const IPAddress& address_queried, |
| bool is_gateway) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeNeighborTableLookup, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultSuccess); |
| RTNLMessage msg(RTNLMessage::kTypeNeighbor, RTNLMessage::kModeAdd, 0, 0, 0, |
| connection_->interface_index(), IPAddress::kFamilyIPv6); |
| msg.set_neighbor_status( |
| RTNLMessage::NeighborStatus(NUD_REACHABLE, 0, NDA_DST)); |
| msg.SetAttribute(NDA_DST, address_queried.address()); |
| const string& issue = |
| is_gateway ? ConnectionDiagnostics::kIssueGatewayNotResponding |
| : ConnectionDiagnostics::kIssueServerNotResponding; |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(issue)); |
| EXPECT_CALL(callback_target(), |
| ResultCallback(issue, IsEventList(expected_events_))); |
| connection_diagnostics_.OnNeighborMsgReceived(address_queried, msg); |
| } |
| |
| void ExpectNeighborTableLookupEndFailureNotReachable( |
| const IPAddress& address_queried, bool is_gateway) { |
| ExpectNeighborTableLookupEndFailure(address_queried, is_gateway, false); |
| } |
| |
| void ExpectNeighborTableLookupEndFailureNoEntry( |
| const IPAddress& address_queried, bool is_gateway) { |
| ExpectNeighborTableLookupEndFailure(address_queried, is_gateway, true); |
| } |
| |
| void ExpectCheckIPCollisionStartSuccess() { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeIPCollisionCheck, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess); |
| EXPECT_CALL(device_info_, GetMACAddress(connection_->interface_index(), _)) |
| .WillOnce( |
| DoAll(SetArgumentPointee<1>(local_mac_address_), Return(true))); |
| EXPECT_CALL(*arp_client_, StartReplyListener()).WillOnce(Return(true)); |
| // We should send an ARP request for our own local IP address. |
| EXPECT_CALL(*arp_client_, TransmitRequest(IsArpRequest( |
| local_ip_address_, local_ip_address_, |
| local_mac_address_, ByteString()))) |
| .WillOnce(Return(true)); |
| EXPECT_CALL(dispatcher_, |
| PostDelayedTask( |
| _, ConnectionDiagnostics::kArpReplyTimeoutSeconds * 1000)); |
| connection_diagnostics_.CheckIpCollision(); |
| } |
| |
| void ExpectCheckIPCollisionEndSuccess() { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeIPCollisionCheck, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultSuccess); |
| // Simulate ARP response from a sender with the same IP address as our |
| // connection, directed at our local IP address and local MAC address. |
| client_test_helper_->GeneratePacket( |
| ARPOP_REPLY, local_ip_address_, |
| ByteString(string(kArpReplySenderMacAddressASCIIString), false), |
| local_ip_address_, local_mac_address_); |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue( |
| ConnectionDiagnostics::kIssueIPCollision)); |
| EXPECT_CALL(callback_target(), |
| ResultCallback(ConnectionDiagnostics::kIssueIPCollision, |
| IsEventList(expected_events_))); |
| connection_diagnostics_.OnArpReplyReceived(1); |
| } |
| |
| void ExpectCheckIPCollisionEndFailureGatewayArpFailed() { |
| ExpectCheckIPCollisionEndFailure( |
| ConnectionDiagnostics::kIssueGatewayArpFailed); |
| } |
| |
| void ExpectCheckIPCollisionEndFailureServerArpFailed() { |
| ExpectCheckIPCollisionEndFailure( |
| ConnectionDiagnostics::kIssueServerArpFailed); |
| } |
| |
| private: |
| void ExpectPortalDetectionEnd(ConnectionDiagnostics::Phase diag_phase, |
| ConnectionDiagnostics::Result diag_result, |
| ConnectivityTrial::Phase trial_phase, |
| ConnectivityTrial::Status trial_status) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypePortalDetection, diag_phase, |
| diag_result); |
| if (diag_phase == ConnectionDiagnostics::kPhasePortalDetectionEndContent) { |
| const string& issue = diag_result == ConnectionDiagnostics::kResultSuccess |
| ? ConnectionDiagnostics::kIssueNone |
| : ConnectionDiagnostics::kIssueCaptivePortal; |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(issue)); |
| EXPECT_CALL(callback_target(), |
| ResultCallback(issue, IsEventList(expected_events_))); |
| |
| } else if (diag_phase == |
| ConnectionDiagnostics::kPhasePortalDetectionEndDNS && |
| diag_result == ConnectionDiagnostics::kResultFailure) { |
| EXPECT_CALL(metrics_, |
| NotifyConnectionDiagnosticsIssue( |
| ConnectionDiagnostics::kIssueDNSServerMisconfig)); |
| EXPECT_CALL( |
| callback_target(), |
| ResultCallback(ConnectionDiagnostics::kIssueDNSServerMisconfig, |
| IsEventList(expected_events_))); |
| } else { |
| // Otherwise, we end in DNS phase with a timeout, or a HTTP phase failure. |
| // Either of these cases warrant further diagnostic actions. |
| EXPECT_CALL(dispatcher_, PostTask(_)); |
| } |
| connection_diagnostics_.StartAfterPortalDetectionInternal( |
| PortalDetector::Result( |
| ConnectivityTrial::Result(trial_phase, trial_status))); |
| } |
| |
| // |expected_issue| only used if |is_success| is false. |
| void ExpectPingDNSSeversStart(bool is_success, const string& expected_issue) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypePingDNSServers, |
| ConnectionDiagnostics::kPhaseStart, |
| is_success ? ConnectionDiagnostics::kResultSuccess |
| : ConnectionDiagnostics::kResultFailure); |
| const char* bad_addresses[] = {"110.2.3", "1.5"}; |
| const vector<string> bad_dns_servers(bad_addresses, bad_addresses + 2); |
| if (!is_success && |
| expected_issue == ConnectionDiagnostics::kIssueDNSServersInvalid) { |
| // If the DNS server addresses are invalid, we will not even attempt to |
| // start any ICMP sessions. |
| EXPECT_CALL(*connection_.get(), dns_servers()) |
| .WillRepeatedly(ReturnRef(bad_dns_servers)); |
| } else { |
| // We are either instrumenting the success case (started pinging all |
| // DNS servers successfully) or the failure case where we fail to start |
| // any pings. |
| ASSERT_TRUE(is_success || |
| expected_issue == ConnectionDiagnostics::kIssueInternalError); |
| dns_server_icmp_session_0_ = new NiceMock<MockIcmpSession>(&dispatcher_); |
| dns_server_icmp_session_1_ = new NiceMock<MockIcmpSession>(&dispatcher_); |
| EXPECT_CALL(*MockIcmpSessionFactory::GetInstance(), |
| CreateIcmpSession(&dispatcher_)) |
| .WillOnce(Return(dns_server_icmp_session_0_)) |
| .WillOnce(Return(dns_server_icmp_session_1_)); |
| EXPECT_CALL(*dns_server_icmp_session_0_, |
| Start(IsSameIPAddress(IPAddress(kDNSServer0)), _)) |
| .WillOnce(Return(is_success)); |
| EXPECT_CALL(*dns_server_icmp_session_1_, |
| Start(IsSameIPAddress(IPAddress(kDNSServer1)), _)) |
| .WillOnce(Return(is_success)); |
| } |
| |
| if (is_success) { |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(_)).Times(0); |
| EXPECT_CALL(callback_target(), ResultCallback(_, _)).Times(0); |
| } else { |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(expected_issue)); |
| EXPECT_CALL( |
| callback_target(), |
| ResultCallback(expected_issue, IsEventList(expected_events_))); |
| } |
| connection_diagnostics_.PingDNSServers(); |
| if (is_success) { |
| EXPECT_EQ(2, connection_diagnostics_ |
| .id_to_pending_dns_server_icmp_session_.size()); |
| } else { |
| EXPECT_TRUE(connection_diagnostics_.id_to_pending_dns_server_icmp_session_ |
| .empty()); |
| } |
| } |
| |
| void ExpectResolveTargetServerIPAddressEnd( |
| ConnectionDiagnostics::Result result, const IPAddress& resolved_address) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeResolveTargetServerIP, |
| ConnectionDiagnostics::kPhaseEnd, result); |
| Error error; |
| if (result == ConnectionDiagnostics::kResultSuccess) { |
| error.Populate(Error::kSuccess); |
| EXPECT_CALL(dispatcher_, PostTask(_)); |
| } else if (result == ConnectionDiagnostics::kResultTimeout) { |
| error.Populate(Error::kOperationTimeout); |
| EXPECT_CALL(dispatcher_, PostTask(_)); |
| } else { |
| error.Populate(Error::kOperationFailed); |
| EXPECT_CALL(metrics_, |
| NotifyConnectionDiagnosticsIssue( |
| ConnectionDiagnostics::kIssueDNSServerMisconfig)); |
| EXPECT_CALL( |
| callback_target(), |
| ResultCallback(ConnectionDiagnostics::kIssueDNSServerMisconfig, |
| IsEventList(expected_events_))); |
| } |
| connection_diagnostics_.OnDNSResolutionComplete(error, resolved_address); |
| } |
| |
| void ExpectPingDNSServersEndSuccess(bool retries_left) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypePingDNSServers, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultSuccess); |
| if (retries_left) { |
| EXPECT_LT(connection_diagnostics_.num_dns_attempts_, |
| ConnectionDiagnostics::kMaxDNSRetries); |
| } else { |
| EXPECT_GE(connection_diagnostics_.num_dns_attempts_, |
| ConnectionDiagnostics::kMaxDNSRetries); |
| } |
| // Post retry task or report done only after all (i.e. 2) pings are done. |
| connection_diagnostics_.OnPingDNSServerComplete(0, kNonEmptyResult); |
| if (retries_left) { |
| EXPECT_CALL(dispatcher_, PostTask(_)); |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(_)).Times(0); |
| EXPECT_CALL(callback_target(), ResultCallback(_, _)).Times(0); |
| } else { |
| EXPECT_CALL(dispatcher_, PostTask(_)).Times(0); |
| EXPECT_CALL(metrics_, |
| NotifyConnectionDiagnosticsIssue( |
| ConnectionDiagnostics::kIssueDNSServerNoResponse)); |
| EXPECT_CALL( |
| callback_target(), |
| ResultCallback(ConnectionDiagnostics::kIssueDNSServerNoResponse, |
| IsEventList(expected_events_))); |
| } |
| connection_diagnostics_.OnPingDNSServerComplete(1, kNonEmptyResult); |
| } |
| |
| void ExpectArpTableLookup(const IPAddress& address, bool success, |
| bool is_gateway) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeArpTableLookup, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess); |
| AddExpectedEvent(ConnectionDiagnostics::kTypeArpTableLookup, |
| ConnectionDiagnostics::kPhaseEnd, |
| success ? ConnectionDiagnostics::kResultSuccess |
| : ConnectionDiagnostics::kResultFailure); |
| EXPECT_CALL(device_info_, |
| GetMACAddressOfPeer(connection_->interface_index(), |
| IsSameIPAddress(address), _)) |
| .WillOnce(Return(success)); |
| if (success) { |
| const string& issue = |
| is_gateway ? ConnectionDiagnostics::kIssueGatewayNotResponding |
| : ConnectionDiagnostics::kIssueServerNotResponding; |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(issue)); |
| EXPECT_CALL(callback_target(), |
| ResultCallback(issue, IsEventList(expected_events_))); |
| } else { |
| // Checking for IP collision. |
| EXPECT_CALL(dispatcher_, PostTask(_)); |
| } |
| connection_diagnostics_.FindArpTableEntry(address); |
| } |
| |
| void ExpectCheckIPCollisionEndFailure(const string& expected_issue) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeIPCollisionCheck, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultFailure); |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(expected_issue)); |
| EXPECT_CALL(callback_target(), |
| ResultCallback(expected_issue, IsEventList(expected_events_))); |
| connection_diagnostics_.OnArpRequestTimeout(); |
| } |
| |
| void ExpectNeighborTableLookupEndFailure(const IPAddress& address_queried, |
| bool is_gateway, bool is_timeout) { |
| AddExpectedEvent(ConnectionDiagnostics::kTypeNeighborTableLookup, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultFailure); |
| string issue; |
| if (is_timeout) { |
| issue = is_gateway ? ConnectionDiagnostics::kIssueGatewayNoNeighborEntry |
| : ConnectionDiagnostics::kIssueServerNoNeighborEntry; |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(issue)); |
| EXPECT_CALL(callback_target(), |
| ResultCallback(issue, IsEventList(expected_events_))); |
| connection_diagnostics_.OnNeighborTableRequestTimeout(address_queried); |
| } else { |
| issue = |
| is_gateway |
| ? ConnectionDiagnostics::kIssueGatewayNeighborEntryNotConnected |
| : ConnectionDiagnostics::kIssueServerNeighborEntryNotConnected; |
| EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(issue)); |
| EXPECT_CALL( |
| callback_target(), |
| ResultCallback(issue, |
| IsEventList(expected_events_))); |
| RTNLMessage msg(RTNLMessage::kTypeNeighbor, RTNLMessage::kModeAdd, 0, 0, |
| 0, connection_->interface_index(), |
| IPAddress::kFamilyIPv6); |
| msg.set_neighbor_status( |
| RTNLMessage::NeighborStatus(NUD_FAILED, 0, NDA_DST)); |
| msg.SetAttribute(NDA_DST, address_queried.address()); |
| connection_diagnostics_.OnNeighborMsgReceived(address_queried, msg); |
| } |
| } |
| |
| const string interface_name_; |
| const vector<string> dns_servers_; |
| const IPAddress local_ip_address_; |
| const IPAddress gateway_ipv4_address_; |
| const IPAddress gateway_ipv6_address_; |
| ByteString local_mac_address_; |
| CallbackTarget callback_target_; |
| MockControl control_; |
| NiceMock<MockMetrics> metrics_; |
| MockManager manager_; |
| NiceMock<MockDeviceInfo> device_info_; |
| scoped_refptr<NiceMock<MockConnection>> connection_; |
| ConnectionDiagnostics connection_diagnostics_; |
| NiceMock<MockEventDispatcher> dispatcher_; |
| NiceMock<MockRoutingTable> routing_table_; |
| NiceMock<MockRTNLHandler> rtnl_handler_; |
| std::unique_ptr<ArpClientTestHelper> client_test_helper_; |
| |
| // Used only for EXPECT_CALL(). Objects are owned by |
| // |connection_diagnostics_|. |
| NiceMock<MockArpClient>* arp_client_; |
| NiceMock<MockDNSClient>* dns_client_; |
| NiceMock<MockIcmpSession>* icmp_session_; |
| NiceMock<MockIcmpSession>* dns_server_icmp_session_0_; |
| NiceMock<MockIcmpSession>* dns_server_icmp_session_1_; |
| NiceMock<MockPortalDetector>* portal_detector_; |
| |
| // For each test, all events we expect to appear in the final result are |
| // accumulated in this vector. |
| vector<ConnectionDiagnostics::Event> expected_events_; |
| }; |
| |
| TEST_F(ConnectionDiagnosticsTest, DoesPreviousEventMatch) { |
| // If |diagnostic_events| is empty, we should always fail to match an event. |
| EXPECT_FALSE( |
| DoesPreviousEventMatch(ConnectionDiagnostics::kTypePortalDetection, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess, 0)); |
| EXPECT_FALSE( |
| DoesPreviousEventMatch(ConnectionDiagnostics::kTypePortalDetection, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess, 2)); |
| |
| AddActualEvent(ConnectionDiagnostics::kTypePortalDetection, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess); |
| AddActualEvent(ConnectionDiagnostics::kTypePortalDetection, |
| ConnectionDiagnostics::kPhasePortalDetectionEndOther, |
| ConnectionDiagnostics::kResultFailure); |
| AddActualEvent(ConnectionDiagnostics::kTypeResolveTargetServerIP, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess); |
| AddActualEvent(ConnectionDiagnostics::kTypeResolveTargetServerIP, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultSuccess); |
| |
| // Matching out of bounds should fail. (4 events total, so 4 events before the |
| // last event is out of bounds). |
| EXPECT_FALSE( |
| DoesPreviousEventMatch(ConnectionDiagnostics::kTypePortalDetection, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess, 4)); |
| |
| // Valid matches. |
| EXPECT_TRUE( |
| DoesPreviousEventMatch(ConnectionDiagnostics::kTypePortalDetection, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess, 3)); |
| EXPECT_TRUE( |
| DoesPreviousEventMatch(ConnectionDiagnostics::kTypeResolveTargetServerIP, |
| ConnectionDiagnostics::kPhaseStart, |
| ConnectionDiagnostics::kResultSuccess, 1)); |
| EXPECT_TRUE( |
| DoesPreviousEventMatch(ConnectionDiagnostics::kTypeResolveTargetServerIP, |
| ConnectionDiagnostics::kPhaseEnd, |
| ConnectionDiagnostics::kResultSuccess, 0)); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, StartWhileRunning) { |
| ExpectPortalDetectionStartSuccess(kURL); // Start diagnostics; |
| EXPECT_FALSE(Start(kURL)); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, StartWithBadURL) { |
| const string kBadURL("http://www.foo.com:x"); // Colon but no port |
| // IcmpSession::Stop will be called once when the bad URL is rejected. |
| ExpectIcmpSessionStop(); |
| EXPECT_FALSE(Start(kBadURL)); |
| // IcmpSession::Stop will be called a second time when |
| // |connection_diagnostics_| is destructed. |
| ExpectIcmpSessionStop(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_InternalError) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, and we |
| // attempt to ping the target web server but fail because of an internal |
| // error. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PortalDetectionContentPhase_Success) { |
| // Portal detection ends successfully in content phase, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndContentPhaseSuccess(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PortalDetectionContentPhase_Failure) { |
| // Portal detection ends unsuccessfully in content phase, so we end |
| // diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndContentPhaseFailure(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_DNSFailure_1) { |
| // Portal detection ends with a DNS failure (not timeout), so we end |
| // diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndDNSPhaseFailure(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_DNSFailure_2) { |
| // Portal detection ends in HTTP phase, DNS resolution fails (not timeout), so |
| // we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndFailure(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingDNSServerStartFailure_1) { |
| // Portal detection ends with a DNS timeout, and we attempt to pinging DNS |
| // servers, but fail to start any IcmpSessions, so end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndDNSPhaseTimeout(); |
| ExpectPingDNSSeversStartFailureAllIcmpSessionsFailed(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingDNSServerStartFailure_2) { |
| // Portal detection ends with a DNS timeout, and we attempt to pinging DNS |
| // servers, but all DNS servers configured for this connection have invalid IP |
| // addresses, so we fail to start ping DNs servers, andend diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndDNSPhaseTimeout(); |
| ExpectPingDNSSeversStartFailureAllAddressesInvalid(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingDNSServerEndSuccess_NoRetries_1) { |
| // Portal detection ends with a DNS timeout, pinging DNS servers succeeds, DNS |
| // resolution times out, pinging DNS servers succeeds again, and DNS |
| // resolution times out again. End diagnostics because we have no more DNS |
| // retries left. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndDNSPhaseTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessRetriesLeft(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessRetriesLeft(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessNoRetriesLeft(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingDNSServerEndSuccess_NoRetries_2) { |
| // Portal detection ends in HTTP phase, DNS resolution times out, pinging DNS |
| // servers succeeds, DNS resolution times out again, pinging DNS servers |
| // succeeds. End diagnostics because we have no more DNS retries left. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessRetriesLeft(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessNoRetriesLeft(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingTargetIPSuccess_1) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, and pinging |
| // the resolved IP address succeeds, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingTargetIPSuccess_2) { |
| // Portal detection ends with a DNS timeout, pinging DNS servers succeeds, DNS |
| // resolution succeeds, and pinging the resolved IP address succeeds, so we |
| // end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndDNSPhaseTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessRetriesLeft(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingTargetIPSuccess_3) { |
| // Portal detection ends in HTTP phase, DNS resolution times out, pinging DNS |
| // servers succeeds, DNS resolution succeeds, and pinging the resolved IP |
| // address succeeds, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessRetriesLeft(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_FindRouteFailure_1) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we fail to get a route for the IP address, |
| // so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndFailure(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_FindRoute_Failure_2) { |
| // Portal detection ends with a DNS timeout, pinging DNS servers succeeds, DNS |
| // resolution succeeds, pinging the resolved IP address fails, and we fail to |
| // get a route for the IP address, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndDNSPhaseTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessRetriesLeft(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndFailure(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_FindRouteFailure_3) { |
| // Portal detection ends in HTTP phase, DNS resolution times out, pinging DNS |
| // servers succeeds, DNS resolution succeeds, pinging the resolved IP address |
| // fails, and we fail to get a route for the IP address, so we end |
| // diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessRetriesLeft(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndFailure(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_FindRouteFailure_4) { |
| // Portal detection ends with a DNS timeout, pinging DNS servers fails, get a |
| // route for the first DNS server, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndDNSPhaseTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndFailure(); |
| ExpectFindRouteToHostStartSuccess(kIPv4GatewayAddress); |
| ExpectFindRouteToHostEndFailure(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingGatewaySuccess_1_IPv4) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we successfully get route for the IP |
| // address. This address is remote, so ping the local gateway and succeed, so |
| // we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv4ServerAddress, false); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| ExpectPingHostEndSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingGatewaySuccess_1_IPv6) { |
| // Same as above, but this time the resolved IP address of the target URL |
| // is IPv6. |
| UseIPv6Gateway(); |
| |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv6); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv6ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv6ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv6ServerAddress, false); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv6GatewayAddress); |
| ExpectPingHostEndSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv6GatewayAddress); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingGatewaySuccess_2) { |
| // Portal detection ends with a DNS timeout, pinging DNS servers succeeds, DNS |
| // resolution succeeds, pinging the resolved IP address fails, and we |
| // successfully get route for the IP address. This address is remote, so ping |
| // the local gateway and succeed, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndDNSPhaseTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessRetriesLeft(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv4ServerAddress, false); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| ExpectPingHostEndSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_PingGatewaySuccess_3) { |
| // Portal detection ends in HTTP phase, DNS resolution times out, pinging DNS |
| // servers succeeds, DNS resolution succeeds, pinging the resolved IP address |
| // fails, and we successfully get route for the IP address. This address is |
| // remote, so ping the local gateway. The ping succeeds, so we end |
| // diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndTimeout(); |
| ExpectPingDNSServersStartSuccess(); |
| ExpectPingDNSServersEndSuccessRetriesLeft(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv4ServerAddress, false); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| ExpectPingHostEndSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| VerifyStopped(); |
| } |
| |
| // Note: for the test below, several other possible paths through the diagnostic |
| // state machine that will lead us to end diagnostics at ARP table lookup or IP |
| // collision check are not explicitly tested. We do this to avoid redundancy |
| // since the above tests have already exercised these sub-paths extensively, |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_FindArpTableEntrySuccess_1) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we successfully get route for the IP |
| // address. This address is remote, pinging the local gateway fails, and we |
| // find an ARP table entry for the gateway address, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv4ServerAddress, false); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| ExpectArpTableLookupStartSuccessEndSuccess(kIPv4GatewayAddress, true); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_FindArpTableEntrySuccess_2) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we successfully get route for the IP |
| // address. This address is local, and we find an ARP table entry for this |
| // address, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv4ServerAddress, true); |
| ExpectArpTableLookupStartSuccessEndSuccess(kIPv4ServerAddress, false); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_IPCollisionSuccess_1) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we successfully get route for the IP |
| // address. This address is remote, pinging the local gateway fails, ARP table |
| // lookup fails, we check for IP collision and find one, so we end |
| // diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv4ServerAddress, false); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| ExpectArpTableLookupStartSuccessEndFailure(kIPv4GatewayAddress); |
| ExpectCheckIPCollisionStartSuccess(); |
| ExpectCheckIPCollisionEndSuccess(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_IPCollisionSuccess_2) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we successfully get route for the IP |
| // address. This address is local, ARP table lookup fails, we check for IP |
| // collision and find one, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv4ServerAddress, true); |
| ExpectArpTableLookupStartSuccessEndSuccess(kIPv4ServerAddress, false); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_IPCollisionFailure_1) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we successfully get route for the IP |
| // address. This address is remote, pinging the local gateway fails, ARP table |
| // lookup fails, we check for IP collision and do not find one, so we end |
| // diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv4ServerAddress, false); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingGateway, |
| kIPv4GatewayAddress); |
| ExpectArpTableLookupStartSuccessEndFailure(kIPv4GatewayAddress); |
| ExpectCheckIPCollisionStartSuccess(); |
| ExpectCheckIPCollisionEndFailureGatewayArpFailed(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_IPCollisionFailure_2) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we successfully get route for the IP |
| // address. This address is local, ARP table lookup fails, we check for IP |
| // collision and do not find one, so we end diagnostics. |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv4); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv4ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv4ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv4ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv4ServerAddress, true); |
| ExpectArpTableLookupStartSuccessEndFailure(kIPv4ServerAddress); |
| ExpectCheckIPCollisionStartSuccess(); |
| ExpectCheckIPCollisionEndFailureServerArpFailed(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_kTypeNeighborTableLookupSuccess_1) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we successfully get route for the IP |
| // address. This address is remote, pinging the local IPv6 gateway fails, |
| // and we find a neighbor table entry for the gateway. End diagnostics. |
| UseIPv6Gateway(); |
| |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv6); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv6ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv6ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv6ServerAddress, false); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv6GatewayAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingGateway, |
| kIPv6GatewayAddress); |
| ExpectNeighborTableLookupStartSuccess(kIPv6GatewayAddress); |
| ExpectNeighborTableLookupEndSuccess(kIPv6GatewayAddress, true); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_kTypeNeighborTableLookupSuccess_2) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, we succeed in getting a route for the IP |
| // address. This address is a local IPv6 address, and we find a neighbor table |
| // entry for it. End diagnostics. |
| UseIPv6Gateway(); |
| |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv6); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv6ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv6ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv6ServerAddress, true); |
| ExpectNeighborTableLookupStartSuccess(kIPv6ServerAddress); |
| ExpectNeighborTableLookupEndSuccess(kIPv6ServerAddress, false); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_kTypeNeighborTableLookupFailure_1) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, and we successfully get route for the IP |
| // address. This address is remote, pinging the local IPv6 gateway fails, and |
| // we find a neighbor table entry for the gateway, but it is not marked as |
| // reachable. End diagnostics. |
| UseIPv6Gateway(); |
| |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv6); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv6ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv6ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv6ServerAddress, false); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingGateway, |
| kIPv6GatewayAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingGateway, |
| kIPv6GatewayAddress); |
| ExpectNeighborTableLookupStartSuccess(kIPv6GatewayAddress); |
| ExpectNeighborTableLookupEndFailureNotReachable(kIPv6GatewayAddress, true); |
| VerifyStopped(); |
| } |
| |
| TEST_F(ConnectionDiagnosticsTest, EndWith_kTypeNeighborTableLookupFailure_2) { |
| // Portal detection ends in HTTP phase, DNS resolution succeeds, pinging the |
| // resolved IP address fails, we succeed in getting a route for the IP |
| // address. This address is a local IPv6 address, and we do not find a |
| // neighbor table entry for it. End diagnostics. |
| UseIPv6Gateway(); |
| |
| ExpectPortalDetectionStartSuccess(kURL); |
| ExpectPortalDetectionEndHTTPPhaseFailure(); |
| ExpectResolveTargetServerIPAddressStartSuccess(IPAddress::kFamilyIPv6); |
| ExpectResolveTargetServerIPAddressEndSuccess(kIPv6ServerAddress); |
| ExpectPingHostStartSuccess(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectPingHostEndFailure(ConnectionDiagnostics::kTypePingTargetServer, |
| kIPv6ServerAddress); |
| ExpectFindRouteToHostStartSuccess(kIPv6ServerAddress); |
| ExpectFindRouteToHostEndSuccess(kIPv6ServerAddress, true); |
| ExpectNeighborTableLookupStartSuccess(kIPv6ServerAddress); |
| ExpectNeighborTableLookupEndFailureNoEntry(kIPv6ServerAddress, false); |
| VerifyStopped(); |
| } |
| |
| } // namespace shill |