// 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.h"

#include <arpa/inet.h>
#include <linux/rtnetlink.h>

#include <memory>
#include <string>
#include <vector>

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include "shill/ipconfig.h"
#include "shill/mock_connection.h"
#include "shill/mock_control.h"
#include "shill/mock_device.h"
#include "shill/mock_device_info.h"
#include "shill/mock_manager.h"
#include "shill/mock_resolver.h"
#include "shill/mock_routing_table.h"
#include "shill/net/mock_rtnl_handler.h"
#include "shill/routing_policy_entry.h"
#include "shill/routing_table_entry.h"

using testing::_;
using testing::AnyNumber;
using testing::Mock;
using testing::Return;
using testing::StrictMock;
using testing::Test;
using testing::WithArg;

namespace shill {

namespace {
const int kDeviceInterfaceIndexBase = 100;

const char kIPAddress0[] = "192.168.1.1";
const char kGatewayAddress0[] = "192.168.1.254";
const char kBroadcastAddress0[] = "192.168.1.255";
const char kNameServer0[] = "8.8.8.8";
const char kNameServer1[] = "8.8.9.9";
const int32_t kPrefix0 = 24;
const int32_t kPrefix1 = 31;
const char kSearchDomain0[] = "chromium.org";
const char kSearchDomain1[] = "google.com";
const char kIPv6Address[] = "2001:db8::1";
const char kIPv6NameServer0[] = "2001:db9::1";
const char kIPv6NameServer1[] = "2001:db9::2";

MATCHER_P2(IsIPAddress, address, prefix, "") {
  IPAddress match_address(address);
  match_address.set_prefix(prefix);
  return match_address.Equals(arg);
}

MATCHER_P(IsIPv6Address, address, "") {
  IPAddress match_address(address);
  return match_address.Equals(arg);
}

MATCHER(IsDefaultAddress, "") {
  IPAddress match_address(arg);
  return match_address.IsDefault();
}

MATCHER_P(IsValidRoutingTableEntry, dst, "") {
  return dst.Equals(arg.dst);
}

MATCHER_P(IsValidThrowRoute, dst, "") {
  return dst.Equals(arg.dst) && arg.type == RTN_THROW;
}

MATCHER_P2(IsValidRoutingRule, family, priority, "") {
  return arg.family == family && arg.priority == priority;
}

MATCHER_P3(IsValidUidRule, family, priority, uid, "") {
  return arg.family == family && arg.priority == priority &&
         arg.uid_range == fib_rule_uid_range{uid, uid};
}

MATCHER_P3(IsValidFwMarkRule, family, priority, fwmark, "") {
  return arg.family == family && arg.priority == priority &&
         arg.fw_mark == fwmark;
}

MATCHER_P3(IsValidIifRule, family, priority, iif, "") {
  return arg.family == family && arg.priority == priority &&
         arg.iif_name == iif;
}

MATCHER_P3(IsValidOifRule, family, priority, oif, "") {
  return arg.family == family && arg.priority == priority &&
         arg.oif_name == oif;
}

MATCHER_P3(IsValidDstRule, family, priority, dst, "") {
  return arg.family == family && arg.priority == priority && arg.dst == dst;
}

MATCHER_P(IsLinkRouteTo, dst, "") {
  return dst.HasSameAddressAs(arg.dst) &&
         arg.dst.prefix() ==
             IPAddress::GetMaxPrefixLength(IPAddress::kFamilyIPv4) &&
         !arg.src.IsValid() && !arg.gateway.IsValid() &&
         arg.scope == RT_SCOPE_LINK;
}

}  // namespace

class ConnectionTest : public Test {
 public:
  ConnectionTest()
      : manager_(&control_, nullptr, nullptr),
        device_info_(new StrictMock<MockDeviceInfo>(&manager_)),
        connection_(nullptr),
        ipconfig_(new IPConfig(&control_, "")),
        ip6config_(new IPConfig(&control_, "")),
        local_address_(IPAddress::kFamilyIPv4),
        broadcast_address_(IPAddress::kFamilyIPv4),
        gateway_address_(IPAddress::kFamilyIPv4),
        default_address_(IPAddress::kFamilyIPv4),
        local_ipv6_address_(IPAddress::kFamilyIPv6) {}

  void SetUp() override {
    properties_.address = kIPAddress0;
    properties_.subnet_prefix = kPrefix0;
    properties_.gateway = kGatewayAddress0;
    properties_.broadcast_address = kBroadcastAddress0;
    properties_.dns_servers = {kNameServer0, kNameServer1};
    properties_.domain_search = {kSearchDomain0, kSearchDomain1};
    properties_.address_family = IPAddress::kFamilyIPv4;
    UpdateProperties();

    ipv6_properties_.address = kIPv6Address;
    ipv6_properties_.dns_servers = {kIPv6NameServer0, kIPv6NameServer1};
    ipv6_properties_.address_family = IPAddress::kFamilyIPv6;
    UpdateIPv6Properties();

    EXPECT_TRUE(local_address_.SetAddressFromString(kIPAddress0));
    EXPECT_TRUE(broadcast_address_.SetAddressFromString(kBroadcastAddress0));
    EXPECT_TRUE(gateway_address_.SetAddressFromString(kGatewayAddress0));
    EXPECT_TRUE(local_ipv6_address_.SetAddressFromString(kIPv6Address));
  }

  void TearDown() override {
    if (connection_) {
      AddDestructorExpectations();
      connection_ = nullptr;
    }
  }

  void UpdateProperties() { ipconfig_->UpdateProperties(properties_, true); }

  void UpdateIPv6Properties() {
    ip6config_->UpdateProperties(ipv6_properties_, true);
  }

  bool GetHasBroadcastDomain() { return connection_->has_broadcast_domain_; }

  bool FixGatewayReachability(const IPAddress& local,
                              IPAddress* peer,
                              IPAddress* gateway) {
    return connection_->FixGatewayReachability(local, peer, gateway);
  }

  void SetMTU(int32_t mtu) { return connection_->SetMTU(mtu); }

  void SetLocal(const IPAddress& local) { connection_->local_ = local; }

  scoped_refptr<MockDevice> CreateDevice(Technology technology) {
    scoped_refptr<MockDevice> device = new StrictMock<MockDevice>(
        &manager_, "test_" + technology.GetName(), std::string(),
        kDeviceInterfaceIndexBase + static_cast<int>(technology));
    EXPECT_CALL(*device, technology()).WillRepeatedly(Return(technology));
    EXPECT_CALL(*device_info_, GetDevice(device->interface_index()))
        .WillRepeatedly(Return(device));
    ON_CALL(*device_info_, GetAddresses(device->interface_index()))
        .WillByDefault(Return(std::vector<IPAddress>{IPAddress(kIPAddress0)}));
    return device;
  }

 protected:
  class DisconnectCallbackTarget {
   public:
    DisconnectCallbackTarget()
        : callback_(base::Bind(&DisconnectCallbackTarget::CallTarget,
                               base::Unretained(this))) {}

    MOCK_METHOD(void, CallTarget, ());
    const base::Closure& callback() const { return callback_; }

   private:
    base::Closure callback_;
  };

  void AddDestructorExpectations() {
    ASSERT_NE(connection_, nullptr);
    EXPECT_CALL(routing_table_, FlushRoutes(connection_->interface_index_));
    EXPECT_CALL(routing_table_,
                FlushRoutesWithTag(connection_->interface_index_));
    EXPECT_CALL(routing_table_, FlushRules(connection_->interface_index_));
    if (connection_->fixed_ip_params_) {
      EXPECT_CALL(*device_info_, FlushAddresses(connection_->interface_index_))
          .Times(0);
    } else {
      EXPECT_CALL(*device_info_, FlushAddresses(connection_->interface_index_));
    }
  }

  void AddIncludedRoutes(const std::vector<IPConfig::Route>& routes) {
    properties_.routes = routes;
    UpdateProperties();

    included_route_dsts_.clear();
    // Add expectations for the added routes.
    auto address_family = properties_.address_family;
    for (const auto& route : routes) {
      IPAddress destination_address(address_family);
      IPAddress source_address(address_family);  // Left as default.
      IPAddress gateway_address(address_family);
      if (!destination_address.SetAddressFromString(route.host) ||
          !gateway_address.SetAddressFromString(route.gateway)) {
        continue;
      }
      destination_address.set_prefix(route.prefix);
      EXPECT_CALL(
          routing_table_,
          AddRoute(connection_->interface_index_,
                   RoutingTableEntry::Create(destination_address,
                                             source_address, gateway_address)
                       .SetMetric(connection_->priority_)
                       .SetTable(connection_->table_id_)));
      included_route_dsts_.push_back(destination_address);
    }
  }

  void AddNonPhysicalRoutingPolicyExpectations(DeviceRefPtr device,
                                               uint32_t priority) {
    EXPECT_CALL(routing_table_, FlushRules(device->interface_index()));

    EXPECT_CALL(routing_table_,
                AddRule(device->interface_index(),
                        IsValidOifRule(IPAddress::kFamilyIPv4, priority,
                                       device->link_name())))
        .WillOnce(Return(true));
    EXPECT_CALL(routing_table_,
                AddRule(device->interface_index(),
                        IsValidOifRule(IPAddress::kFamilyIPv6, priority,
                                       device->link_name())))
        .WillOnce(Return(true));
  }

  void AddPhysicalRoutingPolicyExpectations(DeviceRefPtr device,
                                            uint32_t priority,
                                            bool is_primary_physical) {
    EXPECT_CALL(*device_info_, GetAddresses(device->interface_index()))
        .Times(testing::AnyNumber());

    EXPECT_CALL(routing_table_, FlushRules(device->interface_index()));

    // Primary physical interface will create catch-all for IPv4 and v6.
    // It will also add a main routing table rule above its other rules for both
    // IPv4 and v6.
    if (is_primary_physical) {
      EXPECT_CALL(
          routing_table_,
          AddRule(device->interface_index(),
                  IsValidRoutingRule(IPAddress::kFamilyIPv4, priority - 1)))
          .WillOnce(Return(true));
      EXPECT_CALL(
          routing_table_,
          AddRule(device->interface_index(),
                  IsValidRoutingRule(IPAddress::kFamilyIPv6, priority - 1)))
          .WillOnce(Return(true));

      EXPECT_CALL(routing_table_,
                  AddRule(device->interface_index(),
                          IsValidRoutingRule(IPAddress::kFamilyIPv4,
                                             Connection::kCatchallPriority)))
          .WillOnce(Return(true));
      EXPECT_CALL(routing_table_,
                  AddRule(device->interface_index(),
                          IsValidRoutingRule(IPAddress::kFamilyIPv6,
                                             Connection::kCatchallPriority)))
          .WillOnce(Return(true));
    }

    for (const auto& address :
         device_info_->GetAddresses(device->interface_index())) {
      EXPECT_CALL(routing_table_,
                  AddRule(device->interface_index(),
                          IsValidRoutingRule(address.family(), priority)))
          .WillOnce(Return(true));
    }
    for (const auto& dst : included_route_dsts_) {
      EXPECT_CALL(routing_table_,
                  AddRule(device->interface_index(),
                          IsValidDstRule(dst.family(),
                                         Connection::kDstRulePriority, dst)))
          .WillOnce(Return(true));
    }
    // Physical interfaces will have both iif and oif rules to send to the
    // per-interface table if the interface name matches.
    EXPECT_CALL(routing_table_,
                AddRule(device->interface_index(),
                        IsValidIifRule(IPAddress::kFamilyIPv4, priority,
                                       device->link_name())))
        .WillOnce(Return(true));
    EXPECT_CALL(routing_table_,
                AddRule(device->interface_index(),
                        IsValidIifRule(IPAddress::kFamilyIPv6, priority,
                                       device->link_name())))
        .WillOnce(Return(true));
    EXPECT_CALL(routing_table_,
                AddRule(device->interface_index(),
                        IsValidOifRule(IPAddress::kFamilyIPv4, priority,
                                       device->link_name())))
        .WillOnce(Return(true));
    EXPECT_CALL(routing_table_,
                AddRule(device->interface_index(),
                        IsValidOifRule(IPAddress::kFamilyIPv6, priority,
                                       device->link_name())))
        .WillOnce(Return(true));

    // Physical interfaces will have fwmark rules to send to the per-interface
    // table if the fwmark routing tag matches.
    RoutingPolicyEntry::FwMark routing_fwmark;
    routing_fwmark.value = (1000 + device->interface_index()) << 16;
    routing_fwmark.mask = 0xffff0000;
    EXPECT_CALL(routing_table_,
                AddRule(device->interface_index(),
                        IsValidFwMarkRule(IPAddress::kFamilyIPv4, priority,
                                          routing_fwmark)))
        .WillOnce(Return(true));
    EXPECT_CALL(routing_table_,
                AddRule(device->interface_index(),
                        IsValidFwMarkRule(IPAddress::kFamilyIPv6, priority,
                                          routing_fwmark)))
        .WillOnce(Return(true));
  }

  ConnectionRefPtr CreateConnection(DeviceRefPtr device,
                                    bool fixed_ip_params = false) {
    ConnectionRefPtr connection(new Connection(
        device->interface_index(), device->link_name(), fixed_ip_params,
        device->technology(), device_info_.get(), &control_));
    connection->resolver_ = &resolver_;
    connection->routing_table_ = &routing_table_;
    connection->rtnl_handler_ = &rtnl_handler_;
    return connection;
  }

  MockControl control_;
  MockManager manager_;
  std::unique_ptr<StrictMock<MockDeviceInfo>> device_info_;
  ConnectionRefPtr connection_;
  IPConfigRefPtr ipconfig_;
  IPConfigRefPtr ip6config_;
  IPConfig::Properties properties_;
  IPConfig::Properties ipv6_properties_;
  IPAddress local_address_;
  IPAddress broadcast_address_;
  IPAddress gateway_address_;
  IPAddress default_address_;
  IPAddress local_ipv6_address_;
  std::vector<IPAddress> included_route_dsts_;
  StrictMock<MockResolver> resolver_;
  StrictMock<MockRoutingTable> routing_table_;
  StrictMock<MockRTNLHandler> rtnl_handler_;
};

TEST_F(ConnectionTest, InitState) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  EXPECT_EQ(device->interface_index(), connection_->interface_index());
  EXPECT_EQ(device->link_name(), connection_->interface_name());
  EXPECT_FALSE(connection_->IsDefault());
}

TEST_F(ConnectionTest, AddNonPhysicalDeviceConfig) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  const auto table_id =
      RoutingTable::GetInterfaceTableId(device->interface_index());

  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPAddress(local_address_, kPrefix0)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPAddress(local_address_, kPrefix0),
                                  IsIPAddress(broadcast_address_, 0),
                                  IsIPAddress(default_address_, 0)));
  EXPECT_CALL(routing_table_,
              SetDefaultRoute(device->interface_index(),
                              IsIPAddress(gateway_address_, 0), _, table_id));
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ipconfig_);

  IPAddress test_local_address(local_address_);
  test_local_address.set_prefix(kPrefix0);
  EXPECT_TRUE(test_local_address.Equals(connection_->local()));
  EXPECT_TRUE(gateway_address_.Equals(connection_->gateway()));
  EXPECT_TRUE(GetHasBroadcastDomain());
  EXPECT_FALSE(connection_->IsIPv6());

  // Set default priority and use DNS.
  connection_->SetUseDNS(true);
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kDefaultPriority);
  EXPECT_CALL(resolver_,
              SetDNSFromLists(ipconfig_->properties().dns_servers,
                              ipconfig_->properties().domain_search));
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              SetDefaultMetric(_, Connection::kDefaultPriority));
  connection_->SetPriority(Connection::kDefaultPriority, false);
  EXPECT_TRUE(connection_->IsDefault());
  Mock::VerifyAndClearExpectations(&routing_table_);

  // Set non-default priority and do not use DNS.
  connection_->SetUseDNS(false);
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  EXPECT_CALL(routing_table_, SetDefaultMetric(_, Connection::kLeastPriority));
  connection_->SetPriority(Connection::kLeastPriority, false);
  EXPECT_FALSE(connection_->IsDefault());
}

TEST_F(ConnectionTest, AddNonPhysicalDeviceConfigIncludedRoutes) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  const auto table_id =
      RoutingTable::GetInterfaceTableId(device->interface_index());

  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPAddress(local_address_, kPrefix0)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPAddress(local_address_, kPrefix0),
                                  IsIPAddress(broadcast_address_, 0),
                                  IsIPAddress(default_address_, 0)));
  EXPECT_CALL(routing_table_,
              SetDefaultRoute(device->interface_index(),
                              IsIPAddress(gateway_address_, 0), _, table_id));
  AddIncludedRoutes({{"1.1.1.1", 10, "2.2.2.2"}, {"3.3.3.3", 5, "2.2.2.2"}});
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ipconfig_);

  IPAddress test_local_address(local_address_);
  test_local_address.set_prefix(kPrefix0);
  EXPECT_TRUE(test_local_address.Equals(connection_->local()));
  EXPECT_TRUE(gateway_address_.Equals(connection_->gateway()));
  EXPECT_TRUE(GetHasBroadcastDomain());
  EXPECT_FALSE(connection_->IsIPv6());

  // Set default priority and use DNS.
  connection_->SetUseDNS(true);
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kDefaultPriority);
  EXPECT_CALL(resolver_,
              SetDNSFromLists(ipconfig_->properties().dns_servers,
                              ipconfig_->properties().domain_search));
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              SetDefaultMetric(_, Connection::kDefaultPriority));
  connection_->SetPriority(Connection::kDefaultPriority, false);
  EXPECT_TRUE(connection_->IsDefault());
  Mock::VerifyAndClearExpectations(&routing_table_);

  // Set non-default priority and do not use DNS.
  connection_->SetUseDNS(false);
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  EXPECT_CALL(routing_table_, SetDefaultMetric(_, Connection::kLeastPriority));
  connection_->SetPriority(Connection::kLeastPriority, false);
  EXPECT_FALSE(connection_->IsDefault());
}

TEST_F(ConnectionTest, AddPhysicalDeviceConfig) {
  auto device = CreateDevice(Technology::kEthernet);
  connection_ = CreateConnection(device);

  const auto table_id =
      RoutingTable::GetInterfaceTableId(device->interface_index());

  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPAddress(local_address_, kPrefix0)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPAddress(local_address_, kPrefix0),
                                  IsIPAddress(broadcast_address_, 0),
                                  IsIPAddress(default_address_, 0)));
  EXPECT_CALL(routing_table_,
              SetDefaultRoute(device->interface_index(),
                              IsIPAddress(gateway_address_, 0), _, table_id));
  AddPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority,
                                       false);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ipconfig_);

  IPAddress test_local_address(local_address_);
  test_local_address.set_prefix(kPrefix0);
  EXPECT_TRUE(test_local_address.Equals(connection_->local()));
  EXPECT_TRUE(gateway_address_.Equals(connection_->gateway()));
  EXPECT_TRUE(GetHasBroadcastDomain());
  EXPECT_FALSE(connection_->IsIPv6());

  // Set default priority and use DNS.
  connection_->SetUseDNS(true);
  AddPhysicalRoutingPolicyExpectations(device, Connection::kDefaultPriority,
                                       true);
  EXPECT_CALL(resolver_,
              SetDNSFromLists(ipconfig_->properties().dns_servers,
                              ipconfig_->properties().domain_search));
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              SetDefaultMetric(_, Connection::kDefaultPriority));
  connection_->SetPriority(Connection::kDefaultPriority, true);
  EXPECT_TRUE(connection_->IsDefault());
  Mock::VerifyAndClearExpectations(&routing_table_);

  // Set non-default priority and do not use DNS.
  connection_->SetUseDNS(false);
  AddPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority,
                                       false);
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  EXPECT_CALL(routing_table_, SetDefaultMetric(_, Connection::kLeastPriority));
  connection_->SetPriority(Connection::kLeastPriority, false);
  EXPECT_FALSE(connection_->IsDefault());
}

TEST_F(ConnectionTest, AddPhysicalDeviceConfigIncludedRoutes) {
  auto device = CreateDevice(Technology::kEthernet);
  connection_ = CreateConnection(device);

  const auto table_id =
      RoutingTable::GetInterfaceTableId(device->interface_index());

  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPAddress(local_address_, kPrefix0)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPAddress(local_address_, kPrefix0),
                                  IsIPAddress(broadcast_address_, 0),
                                  IsIPAddress(default_address_, 0)));
  EXPECT_CALL(routing_table_,
              SetDefaultRoute(device->interface_index(),
                              IsIPAddress(gateway_address_, 0), _, table_id));
  AddIncludedRoutes({{"1.1.1.1", 10, "2.2.2.2"}});
  AddPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority,
                                       false);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ipconfig_);

  IPAddress test_local_address(local_address_);
  test_local_address.set_prefix(kPrefix0);
  EXPECT_TRUE(test_local_address.Equals(connection_->local()));
  EXPECT_TRUE(gateway_address_.Equals(connection_->gateway()));
  EXPECT_TRUE(GetHasBroadcastDomain());
  EXPECT_FALSE(connection_->IsIPv6());

  // Set default priority and use DNS.
  connection_->SetUseDNS(true);
  AddPhysicalRoutingPolicyExpectations(device, Connection::kDefaultPriority,
                                       true);
  EXPECT_CALL(resolver_,
              SetDNSFromLists(ipconfig_->properties().dns_servers,
                              ipconfig_->properties().domain_search));
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              SetDefaultMetric(_, Connection::kDefaultPriority));
  connection_->SetPriority(Connection::kDefaultPriority, true);
  EXPECT_TRUE(connection_->IsDefault());
  Mock::VerifyAndClearExpectations(&routing_table_);

  // Set non-default priority and do not use DNS.
  connection_->SetUseDNS(false);
  AddPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority,
                                       false);
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  EXPECT_CALL(routing_table_, SetDefaultMetric(_, Connection::kLeastPriority));
  connection_->SetPriority(Connection::kLeastPriority, false);
  EXPECT_FALSE(connection_->IsDefault());
}

TEST_F(ConnectionTest, AddNonPhysicalDeviceConfigUserTrafficOnly) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  const std::string kExcludeAddress1 = "192.0.1.0/24";
  const std::string kExcludeAddress2 = "192.0.2.0/24";
  const uint32_t uid = 1000;
  RoutingPolicyEntry::FwMark fwmark;
  fwmark.value = 0x1234;
  fwmark.mask = 0xffff;
  IPAddress address1(IPAddress::kFamilyIPv4);
  IPAddress address2(IPAddress::kFamilyIPv4);
  EXPECT_TRUE(address1.SetAddressAndPrefixFromString(kExcludeAddress1));
  EXPECT_TRUE(address2.SetAddressAndPrefixFromString(kExcludeAddress2));

  properties_.allowed_uids = {uid};
  properties_.included_fwmarks = {fwmark};
  properties_.default_route = false;
  properties_.exclusion_list = {kExcludeAddress1, kExcludeAddress2};
  UpdateProperties();

  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPAddress(local_address_, kPrefix0)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPAddress(local_address_, kPrefix0),
                                  IsIPAddress(broadcast_address_, 0),
                                  IsIPAddress(default_address_, 0)));
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));

  // SetupExcludedRoutes should create RTN_THROW entries for both networks.
  EXPECT_CALL(routing_table_,
              AddRoute(device->interface_index(), IsValidThrowRoute(address1)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRoute(device->interface_index(), IsValidThrowRoute(address2)))
      .WillOnce(Return(true));

  // UpdateRoutingPolicy should create uid and fwmark rules for IPv4 and IPv6
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidUidRule(IPAddress::kFamilyIPv4,
                                     Connection::kLeastPriority, uid)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidUidRule(IPAddress::kFamilyIPv6,
                                     Connection::kLeastPriority, uid)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidFwMarkRule(IPAddress::kFamilyIPv4,
                                        Connection::kLeastPriority, fwmark)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidFwMarkRule(IPAddress::kFamilyIPv6,
                                        Connection::kLeastPriority, fwmark)))
      .WillOnce(Return(true));

  connection_->UpdateFromIPConfig(ipconfig_);

  IPAddress test_local_address(local_address_);
  test_local_address.set_prefix(kPrefix0);
  EXPECT_TRUE(test_local_address.Equals(connection_->local()));
  EXPECT_TRUE(gateway_address_.Equals(connection_->gateway()));
  EXPECT_TRUE(GetHasBroadcastDomain());
  EXPECT_FALSE(connection_->IsIPv6());

  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kDefaultPriority);
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidUidRule(IPAddress::kFamilyIPv4,
                                     Connection::kDefaultPriority, uid)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidUidRule(IPAddress::kFamilyIPv6,
                                     Connection::kDefaultPriority, uid)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidFwMarkRule(IPAddress::kFamilyIPv4,
                                        Connection::kDefaultPriority, fwmark)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidFwMarkRule(IPAddress::kFamilyIPv6,
                                        Connection::kDefaultPriority, fwmark)))
      .WillOnce(Return(true));
  EXPECT_CALL(resolver_,
              SetDNSFromLists(ipconfig_->properties().dns_servers,
                              ipconfig_->properties().domain_search));
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  connection_->SetUseDNS(true);
  EXPECT_CALL(routing_table_,
              SetDefaultMetric(_, Connection::kDefaultPriority));
  connection_->SetPriority(Connection::kDefaultPriority, true);
  Mock::VerifyAndClearExpectations(&routing_table_);
  EXPECT_TRUE(connection_->IsDefault());

  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidUidRule(IPAddress::kFamilyIPv4,
                                     Connection::kLeastPriority, uid)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidUidRule(IPAddress::kFamilyIPv6,
                                     Connection::kLeastPriority, uid)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidFwMarkRule(IPAddress::kFamilyIPv4,
                                        Connection::kLeastPriority, fwmark)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_,
              AddRule(device->interface_index(),
                      IsValidFwMarkRule(IPAddress::kFamilyIPv6,
                                        Connection::kLeastPriority, fwmark)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  connection_->SetUseDNS(false);
  EXPECT_CALL(routing_table_, SetDefaultMetric(_, Connection::kLeastPriority));
  connection_->SetPriority(Connection::kLeastPriority, false);
  EXPECT_FALSE(connection_->IsDefault());
}

TEST_F(ConnectionTest, AddNonPhysicalDeviceConfigIPv6) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPv6Address(local_ipv6_address_)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPv6Address(local_ipv6_address_),
                                  IsDefaultAddress(), _));
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ip6config_);

  IPAddress test_local_address(local_ipv6_address_);
  EXPECT_TRUE(test_local_address.Equals(connection_->local()));
  EXPECT_TRUE(connection_->IsIPv6());
}

TEST_F(ConnectionTest, AddPhysicalDeviceConfigIPv6) {
  auto device = CreateDevice(Technology::kEthernet);
  connection_ = CreateConnection(device);

  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPv6Address(local_ipv6_address_)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPv6Address(local_ipv6_address_),
                                  IsDefaultAddress(), _));
  AddPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority,
                                       false);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ip6config_);

  IPAddress test_local_address(local_ipv6_address_);
  EXPECT_TRUE(test_local_address.Equals(connection_->local()));
  EXPECT_TRUE(connection_->IsIPv6());
}

TEST_F(ConnectionTest, AddConfigWithPeer) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  const std::string kPeerAddress("192.168.1.222");
  IPAddress peer_address(IPAddress::kFamilyIPv4);
  EXPECT_TRUE(peer_address.SetAddressFromString(kPeerAddress));
  properties_.peer_address = kPeerAddress;
  properties_.gateway = std::string();
  UpdateProperties();
  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPAddress(local_address_, kPrefix0)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPAddress(local_address_, kPrefix0),
                                  IsIPAddress(broadcast_address_, 0), _));
  EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _, _)).Times(1);
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ipconfig_);
  EXPECT_FALSE(GetHasBroadcastDomain());
}

TEST_F(ConnectionTest, AddConfigWithBrokenNetmask) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  // Assign a prefix that makes the gateway unreachable.
  properties_.subnet_prefix = kPrefix1;
  UpdateProperties();

  const auto table_id =
      RoutingTable::GetInterfaceTableId(device->interface_index());

  // Connection should add a link route which will allow the
  // gateway to be reachable.
  IPAddress gateway_address(IPAddress::kFamilyIPv4);
  EXPECT_TRUE(gateway_address.SetAddressFromString(kGatewayAddress0));
  EXPECT_CALL(routing_table_, AddRoute(device->interface_index(),
                                       IsLinkRouteTo(gateway_address)))
      .WillOnce(Return(true));
  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPAddress(local_address_, kPrefix1)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPAddress(local_address_, kPrefix1),
                                  IsIPAddress(broadcast_address_, 0),
                                  IsIPAddress(default_address_, 0)));
  EXPECT_CALL(routing_table_,
              SetDefaultRoute(device->interface_index(),
                              IsIPAddress(gateway_address_, 0), _, table_id));

  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ipconfig_);
}

TEST_F(ConnectionTest, AddConfigReverse) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kDefaultPriority);

  std::vector<std::string> empty_list;
  EXPECT_CALL(resolver_, SetDNSFromLists(empty_list, empty_list));
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  connection_->SetUseDNS(true);
  EXPECT_CALL(routing_table_,
              SetDefaultMetric(_, Connection::kDefaultPriority));
  connection_->SetPriority(Connection::kDefaultPriority, true);
  Mock::VerifyAndClearExpectations(&routing_table_);

  const auto table_id =
      RoutingTable::GetInterfaceTableId(device->interface_index());

  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPAddress(local_address_, kPrefix0)))
      .WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPAddress(local_address_, kPrefix0),
                                  IsIPAddress(broadcast_address_, 0),
                                  IsIPAddress(default_address_, 0)));
  EXPECT_CALL(routing_table_,
              SetDefaultRoute(device->interface_index(),
                              IsIPAddress(gateway_address_, 0),
                              Connection::kDefaultPriority, table_id));
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kDefaultPriority);
  EXPECT_CALL(resolver_,
              SetDNSFromLists(ipconfig_->properties().dns_servers,
                              ipconfig_->properties().domain_search));
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ipconfig_);
}

TEST_F(ConnectionTest, AddConfigWithDNSDomain) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  const std::string kDomainName("chromium.org");
  properties_.domain_search.clear();
  properties_.domain_name = kDomainName;
  UpdateProperties();
  EXPECT_CALL(*device_info_, HasOtherAddress(_, _)).WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _));
  EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _, _));
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(_, _));
  connection_->UpdateFromIPConfig(ipconfig_);

  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kDefaultPriority);
  std::vector<std::string> domain_search_list = {kDomainName + "."};
  EXPECT_CALL(resolver_, SetDNSFromLists(_, domain_search_list));
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  connection_->SetUseDNS(true);
  EXPECT_CALL(routing_table_,
              SetDefaultMetric(_, Connection::kDefaultPriority));
  connection_->SetPriority(Connection::kDefaultPriority, true);
}

TEST_F(ConnectionTest, AddConfigWithFixedIpParams) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device, true);

  // Initial setup: routes but no IP configuration.
  EXPECT_CALL(*device_info_, HasOtherAddress(_, _)).Times(0);
  EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _)).Times(0);
  EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _, _));
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(_, _)).Times(0);
  connection_->UpdateFromIPConfig(ipconfig_);
  Mock::VerifyAndClearExpectations(&routing_table_);
  Mock::VerifyAndClearExpectations(&rtnl_handler_);

  // Change priority to make this the default service.
  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kDefaultPriority);
  EXPECT_CALL(resolver_, SetDNSFromLists(_, _));
  EXPECT_CALL(routing_table_, FlushCache()).WillOnce(Return(true));
  connection_->SetUseDNS(true);
  EXPECT_CALL(routing_table_,
              SetDefaultMetric(_, Connection::kDefaultPriority));
  connection_->SetPriority(Connection::kDefaultPriority, false);
}

TEST_F(ConnectionTest, HasOtherAddress) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  const auto table_id =
      RoutingTable::GetInterfaceTableId(device->interface_index());
  EXPECT_CALL(*device_info_,
              HasOtherAddress(device->interface_index(),
                              IsIPAddress(local_address_, kPrefix0)))
      .WillOnce(Return(true));
  EXPECT_CALL(routing_table_, FlushRoutes(device->interface_index()));
  EXPECT_CALL(*device_info_, FlushAddresses(device->interface_index()));
  EXPECT_CALL(rtnl_handler_,
              AddInterfaceAddress(device->interface_index(),
                                  IsIPAddress(local_address_, kPrefix0),
                                  IsIPAddress(broadcast_address_, 0),
                                  IsIPAddress(default_address_, 0)));
  EXPECT_CALL(routing_table_,
              SetDefaultRoute(device->interface_index(),
                              IsIPAddress(gateway_address_, 0), _, table_id));
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));

  AddNonPhysicalRoutingPolicyExpectations(device, Connection::kLeastPriority);

  connection_->UpdateFromIPConfig(ipconfig_);
}

TEST_F(ConnectionTest, UpdateDNSServers) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  static const char* const kDnsServers[] = {"1.1.1.1", "1.1.1.2"};
  std::vector<std::string> dns_servers(kDnsServers, std::end(kDnsServers));

  // Non-default connection.
  EXPECT_CALL(resolver_, SetDNSFromLists(_, _)).Times(0);
  connection_->UpdateDNSServers(dns_servers);
  Mock::VerifyAndClearExpectations(&resolver_);

  // Default connection.
  connection_->SetUseDNS(true);
  EXPECT_CALL(resolver_, SetDNSFromLists(dns_servers, _));
  connection_->UpdateDNSServers(dns_servers);
  Mock::VerifyAndClearExpectations(&resolver_);
}

TEST_F(ConnectionTest, BlackholeIPv6) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  const auto table_id =
      RoutingTable::GetInterfaceTableId(device->interface_index());
  properties_.blackhole_ipv6 = true;
  UpdateProperties();
  EXPECT_CALL(*device_info_, HasOtherAddress(_, _)).WillOnce(Return(false));
  EXPECT_CALL(rtnl_handler_, AddInterfaceAddress(_, _, _, _));
  EXPECT_CALL(routing_table_, SetDefaultRoute(_, _, _, _));
  EXPECT_CALL(routing_table_, FlushRules(_));
  EXPECT_CALL(routing_table_, AddRule(_, _)).WillRepeatedly(Return(true));
  EXPECT_CALL(routing_table_,
              CreateBlackholeRoute(device->interface_index(),
                                   IPAddress::kFamilyIPv6, 0, table_id))
      .WillOnce(Return(true));
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  connection_->UpdateFromIPConfig(ipconfig_);
}

TEST_F(ConnectionTest, FixGatewayReachability) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  static const char kLocal[] = "10.242.2.13";
  IPAddress local(IPAddress::kFamilyIPv4);
  ASSERT_TRUE(local.SetAddressFromString(kLocal));
  const int kPrefix = 24;
  local.set_prefix(kPrefix);
  IPAddress gateway(IPAddress::kFamilyIPv4);
  IPAddress peer(IPAddress::kFamilyIPv4);

  // Should fail because no gateway is set and peer address is invalid.
  EXPECT_FALSE(FixGatewayReachability(local, &peer, &gateway));
  EXPECT_EQ(kPrefix, local.prefix());
  EXPECT_FALSE(peer.IsValid());
  EXPECT_FALSE(gateway.IsValid());

  // Should succeed because with the given prefix, this gateway is reachable.
  static const char kReachableGateway[] = "10.242.2.14";
  ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
  IPAddress gateway_backup(gateway);
  peer = IPAddress(IPAddress::kFamilyIPv4);
  EXPECT_TRUE(FixGatewayReachability(local, &peer, &gateway));
  // Prefix should remain unchanged.
  EXPECT_EQ(kPrefix, local.prefix());
  // Peer should remain unchanged.
  EXPECT_FALSE(peer.IsValid());
  // Gateway should remain unchanged.
  EXPECT_TRUE(gateway_backup.Equals(gateway));

  // Should succeed because we created a link route to the gateway.
  static const char kRemoteGateway[] = "10.242.3.14";
  ASSERT_TRUE(gateway.SetAddressFromString(kRemoteGateway));
  gateway_backup = gateway;
  gateway_backup.SetAddressToDefault();
  peer = IPAddress(IPAddress::kFamilyIPv4);
  EXPECT_CALL(routing_table_,
              AddRoute(device->interface_index(), IsLinkRouteTo(gateway)))
      .WillOnce(Return(true));
  EXPECT_TRUE(FixGatewayReachability(local, &peer, &gateway));

  // Invalid peer should not be modified.
  EXPECT_FALSE(peer.IsValid());
  // Gateway should not be set to default.
  EXPECT_FALSE(gateway_backup.Equals(gateway));

  // Should fail if AddRoute() fails.
  EXPECT_CALL(routing_table_,
              AddRoute(device->interface_index(), IsLinkRouteTo(gateway)))
      .WillOnce(Return(false));
  EXPECT_FALSE(FixGatewayReachability(local, &peer, &gateway));

  // Even if there is a peer specified and it does not match the gateway, we
  // should not fail.
  local.set_prefix(kPrefix);
  ASSERT_TRUE(gateway.SetAddressFromString(kReachableGateway));
  EXPECT_TRUE(FixGatewayReachability(local, &peer, &gateway));
  EXPECT_EQ(kPrefix, local.prefix());
  EXPECT_FALSE(peer.Equals(gateway));

  // If this is a peer-to-peer interface and the peer matches the gateway, the
  // gateway and peer address should be modified to allow routing to work
  // correctly.
  static const char kUnreachableGateway[] = "11.242.2.14";
  ASSERT_TRUE(gateway.SetAddressFromString(kUnreachableGateway));
  ASSERT_TRUE(peer.SetAddressFromString(kUnreachableGateway));
  EXPECT_TRUE(FixGatewayReachability(local, &peer, &gateway));
  EXPECT_TRUE(peer.IsDefault());
  EXPECT_TRUE(gateway.IsDefault());
}

TEST_F(ConnectionTest, GetSubnetName) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  EXPECT_EQ("", connection_->GetSubnetName());
  IPAddress local("1.2.3.4");
  local.set_prefix(24);
  SetLocal(local);
  EXPECT_EQ("1.2.3.0/24", connection_->GetSubnetName());
}

TEST_F(ConnectionTest, SetMTU) {
  auto device = CreateDevice(Technology::kUnknown);
  connection_ = CreateConnection(device);

  testing::InSequence seq;
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  SetMTU(0);

  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kDefaultMTU));
  SetMTU(IPConfig::kUndefinedMTU);

  // Test IPv4 minimum MTU.
  SetLocal(local_address_);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kMinIPv4MTU));
  SetMTU(1);

  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kMinIPv4MTU));
  SetMTU(IPConfig::kMinIPv4MTU - 1);

  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kMinIPv4MTU));
  SetMTU(IPConfig::kMinIPv4MTU);

  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kMinIPv4MTU + 1));
  SetMTU(IPConfig::kMinIPv4MTU + 1);

  // Test IPv6 minimum MTU.
  SetLocal(local_ipv6_address_);
  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kMinIPv6MTU));
  SetMTU(1);

  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kMinIPv6MTU));
  SetMTU(IPConfig::kMinIPv6MTU - 1);

  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kMinIPv6MTU));
  SetMTU(IPConfig::kMinIPv6MTU);

  EXPECT_CALL(rtnl_handler_, SetInterfaceMTU(device->interface_index(),
                                             IPConfig::kMinIPv6MTU + 1));
  SetMTU(IPConfig::kMinIPv6MTU + 1);
}

}  // namespace shill
