// Copyright 2018 The Chromium OS 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 "shill/connection_diagnostics.h"

#include <linux/rtnetlink.h>
#include <net/if_arp.h>

#include <memory>
#include <utility>

#include <gtest/gtest.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/arp_client.h"
#include "shill/net/mock_io_handler_factory.h"
#include "shill/net/mock_rtnl_handler.h"
#include "shill/routing_table_entry.h"

using base::Bind;
using base::Callback;
using base::Unretained;
using std::string;
using std::vector;
using testing::_;
using testing::ByMove;
using testing::NiceMock;
using testing::Return;
using testing::ReturnRef;
using testing::ReturnRefOfCopy;
using testing::SetArgPointee;
using testing::Test;

namespace {
const char kInterfaceName[] = "int0";
const char kDNSServer0[] = "8.8.8.8";
const char kDNSServer1[] = "8.8.4.4";
const char kHttpUrl[] = "http://www.gstatic.com/generate_204";
const char kHttpsUrl[] = "https://www.google.com/generate_204";
const vector<string> kFallbackHttpUrls{
    "http://www.google.com/gen_204",
    "http://play.googleapis.com/generate_204",
};
const char kLocalMacAddressASCIIString[] = "123456";
const char kArpReplySenderMacAddressASCIIString[] = "345678";
const char* const 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 shill::IPAddress kIPv4ZeroAddress("0.0.0.0");
const vector<base::TimeDelta> kEmptyResult;
const vector<base::TimeDelta> kNonEmptyResult{
    base::TimeDelta::FromMilliseconds(10)};
const uint8_t kMacZeroAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
}  // 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),
        manager_(&control_, &dispatcher_, &metrics_),
        device_info_(&manager_),
        connection_(new NiceMock<MockConnection>(&device_info_)),
        connection_diagnostics_(connection_,
                                &dispatcher_,
                                &metrics_,
                                &device_info_,
                                callback_target_.result_callback()),
        portal_detector_(new NiceMock<MockPortalDetector>(connection_)) {
    connection_diagnostics_.io_handler_factory_ = &io_handler_factory_;
  }

  ~ConnectionDiagnosticsTest() override = default;

  void SetUp() override {
    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_, interface_name())
        .WillByDefault(ReturnRef(interface_name_));
    ON_CALL(*connection_, dns_servers()).WillByDefault(ReturnRef(dns_servers_));
    ON_CALL(*connection_, gateway())
        .WillByDefault(ReturnRef(gateway_ipv4_address_));
    ON_CALL(*connection_, local()).WillByDefault(ReturnRef(local_ip_address_));
    connection_diagnostics_.dns_client_factory_ =
        MockDnsClientFactory::GetInstance();
    connection_diagnostics_.icmp_session_factory_ =
        MockIcmpSessionFactory::GetInstance();
  }

  void TearDown() override {}

 protected:
  class CallbackTarget {
   public:
    CallbackTarget()
        : result_callback_(
              Bind(&CallbackTarget::ResultCallback, Unretained(this))) {}

    MOCK_METHOD(void,
                ResultCallback,
                (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_, 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 PortalDetector::Properties& props) {
    return connection_diagnostics_.Start(props);
  }

  void VerifyStopped() {
    EXPECT_FALSE(connection_diagnostics_.running());
    EXPECT_EQ(0, connection_diagnostics_.num_dns_attempts_);
    EXPECT_TRUE(connection_diagnostics_.diagnostic_events_.empty());
    EXPECT_EQ(nullptr, connection_diagnostics_.dns_client_);
    EXPECT_FALSE(connection_diagnostics_.arp_client_->IsStarted());
    EXPECT_FALSE(connection_diagnostics_.icmp_session_->IsStarted());
    EXPECT_EQ(nullptr, connection_diagnostics_.portal_detector_);
    EXPECT_EQ(nullptr, connection_diagnostics_.receive_response_handler_);
    EXPECT_EQ(nullptr, connection_diagnostics_.neighbor_msg_listener_);
    EXPECT_TRUE(
        connection_diagnostics_.id_to_pending_dns_server_icmp_session_.empty());
    EXPECT_EQ(nullptr, connection_diagnostics_.target_url_);
    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(PortalDetector::Properties props) {
    AddExpectedEvent(ConnectionDiagnostics::kTypePortalDetection,
                     ConnectionDiagnostics::kPhaseStart,
                     ConnectionDiagnostics::kResultSuccess);
    EXPECT_CALL(*portal_detector_, StartAfterDelay(props, 0))
        .WillOnce(Return(true));
    EXPECT_FALSE(connection_diagnostics_.running());
    EXPECT_TRUE(connection_diagnostics_.diagnostic_events_.empty());
    EXPECT_TRUE(Start(props));
    EXPECT_TRUE(connection_diagnostics_.running());
  }

  void ExpectPortalDetectionEndContentPhaseSuccess() {
    ExpectPortalDetectionEnd(
        ConnectionDiagnostics::kPhasePortalDetectionEndContent,
        ConnectionDiagnostics::kResultSuccess, PortalDetector::Phase::kContent,
        PortalDetector::Status::kSuccess);
  }

  void ExpectPortalDetectionEndContentPhaseFailure() {
    ExpectPortalDetectionEnd(
        ConnectionDiagnostics::kPhasePortalDetectionEndContent,
        ConnectionDiagnostics::kResultFailure, PortalDetector::Phase::kContent,
        PortalDetector::Status::kFailure);
  }

  void ExpectPortalDetectionEndDNSPhaseFailure() {
    ExpectPortalDetectionEnd(ConnectionDiagnostics::kPhasePortalDetectionEndDNS,
                             ConnectionDiagnostics::kResultFailure,
                             PortalDetector::Phase::kDNS,
                             PortalDetector::Status::kFailure);
  }

  void ExpectPortalDetectionEndDNSPhaseTimeout() {
    ExpectPortalDetectionEnd(ConnectionDiagnostics::kPhasePortalDetectionEndDNS,
                             ConnectionDiagnostics::kResultTimeout,
                             PortalDetector::Phase::kDNS,
                             PortalDetector::Status::kTimeout);
  }

  void ExpectPortalDetectionEndHTTPPhaseFailure() {
    ExpectPortalDetectionEnd(
        ConnectionDiagnostics::kPhasePortalDetectionEndOther,
        ConnectionDiagnostics::kResultFailure, PortalDetector::Phase::kHTTP,
        PortalDetector::Status::kFailure);
  }

  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_, PostDelayedTask(_, _, 0));
    connection_diagnostics_.OnPingDNSServerComplete(1, kEmptyResult);
  }

  void ExpectResolveTargetServerIPAddressStartSuccess(
      IPAddress::Family family) {
    AddExpectedEvent(ConnectionDiagnostics::kTypeResolveTargetServerIP,
                     ConnectionDiagnostics::kPhaseStart,
                     ConnectionDiagnostics::kResultSuccess);
    ASSERT_FALSE(family == IPAddress::kFamilyUnknown);

    auto dns_client = std::make_unique<NiceMock<MockDnsClient>>();
    EXPECT_CALL(*dns_client,
                Start(connection_diagnostics_.target_url_->host(), _))
        .WillOnce(Return(true));
    EXPECT_CALL(*connection_, IsIPv6())
        .WillOnce(Return(family == IPAddress::kFamilyIPv6));
    EXPECT_CALL(
        *MockDnsClientFactory::GetInstance(),
        CreateDnsClient(family, kInterfaceName, dns_servers_,
                        DnsClient::kDnsTimeoutMilliseconds, &dispatcher_, _))
        .WillOnce(Return(ByMove(std::move(dns_client))));
    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_, PostDelayedTask(_, _, 0));
    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_, PostDelayedTask(_, _, 0));
    auto entry =
        RoutingTableEntry::Create(address_queried,
                                  IPAddress(address_queried.family()), gateway)
            .SetTable(connection_->table_id());
    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(SetArgPointee<1>(local_mac_address_), Return(true)));
    EXPECT_CALL(*arp_client_, StartReplyListener()).WillOnce(Return(true));
    // We should send an ARP probe request for our own local IP address.
    EXPECT_CALL(*arp_client_,
                TransmitRequest(IsArpRequest(
                    kIPv4ZeroAddress, local_ip_address_, local_mac_address_,
                    ByteString(kMacZeroAddress, sizeof(kMacZeroAddress)))))
        .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,
                                PortalDetector::Phase trial_phase,
                                PortalDetector::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_, PostDelayedTask(_, _, 0));
    }
    connection_diagnostics_.StartAfterPortalDetectionInternal(
        PortalDetector::Result(trial_phase, trial_status),
        PortalDetector::Result(PortalDetector::Phase::kContent,
                               PortalDetector::Status::kSuccess));
  }

  // |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);
    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_, dns_servers())
          .WillRepeatedly(ReturnRefOfCopy(vector<string>{"110.2.3", "1.5"}));
    } 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);

      auto dns_server_icmp_session_0 =
          std::make_unique<NiceMock<MockIcmpSession>>(&dispatcher_);
      auto dns_server_icmp_session_1 =
          std::make_unique<NiceMock<MockIcmpSession>>(&dispatcher_);

      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));

      EXPECT_CALL(*MockIcmpSessionFactory::GetInstance(),
                  CreateIcmpSession(&dispatcher_))
          .WillOnce(Return(ByMove(std::move(dns_server_icmp_session_0))))
          .WillOnce(Return(ByMove(std::move(dns_server_icmp_session_1))));
    }

    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_, PostDelayedTask(_, _, 0));
    } else if (result == ConnectionDiagnostics::kResultTimeout) {
      error.Populate(Error::kOperationTimeout);
      EXPECT_CALL(dispatcher_, PostDelayedTask(_, _, 0));
    } 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_, PostDelayedTask(_, _, 0));
      EXPECT_CALL(metrics_, NotifyConnectionDiagnosticsIssue(_)).Times(0);
      EXPECT_CALL(callback_target(), ResultCallback(_, _)).Times(0);
    } else {
      EXPECT_CALL(dispatcher_, PostDelayedTask(_, _, 0)).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_, PostDelayedTask(_, _, 0));
    }
    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_;
  MockIOHandlerFactory io_handler_factory_;
  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<MockIcmpSession>* icmp_session_;
  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) {
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);  // Start diagnostics;
  EXPECT_FALSE(Start(props));
}

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();
  PortalDetector::Properties props =
      PortalDetector::Properties(kBadURL, kHttpsUrl, kFallbackHttpUrls);
  EXPECT_FALSE(Start(props));
  // 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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  ExpectPortalDetectionEndContentPhaseSuccess();
  VerifyStopped();
}

TEST_F(ConnectionDiagnosticsTest, EndWith_PortalDetectionContentPhase_Failure) {
  // Portal detection ends unsuccessfully in content phase, so we end
  // diagnostics.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  ExpectPortalDetectionEndContentPhaseFailure();
  VerifyStopped();
}

TEST_F(ConnectionDiagnosticsTest, EndWith_DNSFailure_1) {
  // Portal detection ends with a DNS failure (not timeout), so we end
  // diagnostics.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  ExpectPortalDetectionEndDNSPhaseFailure();
  VerifyStopped();
}

TEST_F(ConnectionDiagnosticsTest, EndWith_DNSFailure_2) {
  // Portal detection ends in HTTP phase, DNS resolution fails (not timeout), so
  // we end diagnostics.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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();

  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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.
  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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();

  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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();

  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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();

  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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();

  PortalDetector::Properties props =
      PortalDetector::Properties(kHttpUrl, kHttpsUrl, kFallbackHttpUrls);
  ExpectPortalDetectionStartSuccess(props);
  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
