// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/network_change_notifier_fuchsia.h"

#include <fuchsia/net/interfaces/cpp/fidl_test_base.h>
#include <lib/fidl/cpp/binding.h>

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

#include "base/auto_reset.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/threading/sequence_bound.h"
#include "base/threading/thread.h"
#include "net/base/ip_address.h"
#include "net/base/network_change_notifier.h"
#include "net/dns/dns_config_service.h"
#include "net/dns/system_dns_config_change_notifier.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net {
namespace {

enum : uint32_t { kDefaultInterfaceId = 1, kSecondaryInterfaceId = 2 };

using IPv4Octets = std::array<uint8_t, 4>;
using IPv6Octets = std::array<uint8_t, 16>;

constexpr IPv4Octets kDefaultIPv4Address = {192, 168, 0, 2};
constexpr uint8_t kDefaultIPv4Prefix = 16;
constexpr IPv4Octets kSecondaryIPv4Address = {10, 0, 0, 1};
constexpr uint8_t kSecondaryIPv4Prefix = 8;

constexpr IPv6Octets kDefaultIPv6Address = {0x20, 0x01, 0x01};
constexpr uint8_t kDefaultIPv6Prefix = 16;
constexpr IPv6Octets kSecondaryIPv6Address = {0x20, 0x01, 0x02};
constexpr uint8_t kSecondaryIPv6Prefix = 16;

constexpr const char kDefaultInterfaceName[] = "net1";
constexpr const char kSecondaryInterfaceName[] = "net2";

fuchsia::net::IpAddress IpAddressFrom(IPv4Octets octets) {
  fuchsia::net::IpAddress output;
  output.ipv4().addr = octets;
  return output;
}

fuchsia::net::IpAddress IpAddressFrom(IPv6Octets octets) {
  fuchsia::net::IpAddress output;
  output.ipv6().addr = octets;
  return output;
}

template <typename T>
fuchsia::net::Subnet SubnetFrom(T octets, uint8_t prefix) {
  fuchsia::net::Subnet output;
  output.addr = IpAddressFrom(octets);
  output.prefix_len = prefix;
  return output;
}

template <typename T>
fuchsia::net::interfaces::Address InterfaceAddressFrom(T octets,
                                                       uint8_t prefix) {
  fuchsia::net::interfaces::Address addr;
  addr.set_addr(SubnetFrom(octets, prefix));
  return addr;
}

template <typename T>
std::vector<T> MakeSingleItemVec(T item) {
  std::vector<T> vec;
  vec.push_back(std::move(item));
  return vec;
}

fuchsia::net::interfaces::Properties DefaultInterfaceProperties(
    fuchsia::hardware::network::DeviceClass device_class =
        fuchsia::hardware::network::DeviceClass::ETHERNET) {
  // For most tests a live interface with an IPv4 address and ethernet class is
  // sufficient.
  fuchsia::net::interfaces::Properties interface;
  interface.set_id(kDefaultInterfaceId);
  interface.set_name(kDefaultInterfaceName);
  interface.set_online(true);
  interface.set_has_default_ipv4_route(true);
  interface.set_has_default_ipv6_route(true);
  interface.set_device_class(fuchsia::net::interfaces::DeviceClass::WithDevice(
      std::move(device_class)));
  interface.set_addresses(MakeSingleItemVec(
      InterfaceAddressFrom(kDefaultIPv4Address, kDefaultIPv4Prefix)));
  return interface;
}

fuchsia::net::interfaces::Properties SecondaryInterfaceProperties() {
  // For most tests a live interface with an IPv4 address and ethernet class is
  // sufficient.
  fuchsia::net::interfaces::Properties interface;
  interface.set_id(kSecondaryInterfaceId);
  interface.set_name(kSecondaryInterfaceName);
  interface.set_online(true);
  interface.set_has_default_ipv4_route(false);
  interface.set_has_default_ipv6_route(false);
  interface.set_device_class(fuchsia::net::interfaces::DeviceClass::WithDevice(
      fuchsia::hardware::network::DeviceClass::ETHERNET));
  interface.set_addresses(MakeSingleItemVec(
      InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
  return interface;
}

template <typename F>
fuchsia::net::interfaces::Event MakeChangeEvent(uint64_t interface_id, F fn) {
  fuchsia::net::interfaces::Properties props;
  props.set_id(interface_id);
  fn(&props);
  return fuchsia::net::interfaces::Event::WithChanged(std::move(props));
}

// Partial fake implementation of a fuchsia.net.interfaces/Watcher.
class FakeWatcher : public fuchsia::net::interfaces::testing::Watcher_TestBase {
 public:
  FakeWatcher() : binding_(this) {
    // Always create the watcher with an empty set of interfaces.
    // Callers can override the initial set of events with SetInitial.
    pending_.push(fuchsia::net::interfaces::Event::WithIdle(
        fuchsia::net::interfaces::Empty{}));
  }
  FakeWatcher(const FakeWatcher&) = delete;
  FakeWatcher& operator=(const FakeWatcher&) = delete;
  ~FakeWatcher() override = default;

  void Bind(fidl::InterfaceRequest<fuchsia::net::interfaces::Watcher> request) {
    CHECK_EQ(ZX_OK, binding_.Bind(std::move(request)));
  }

  void Unbind() { binding_.Unbind(); }

  void PushEvent(fuchsia::net::interfaces::Event event) {
    if (pending_callback_) {
      pending_callback_(std::move(event));
      pending_callback_ = nullptr;
    } else {
      pending_.push(std::move(event));
    }
  }

  void SetInitial(std::vector<fuchsia::net::interfaces::Properties> props) {
    // Discard any pending events.
    pending_ = std::queue<fuchsia::net::interfaces::Event>();
    for (auto& prop : props) {
      pending_.push(
          fuchsia::net::interfaces::Event::WithExisting(std::move(prop)));
    }
    pending_.push(fuchsia::net::interfaces::Event::WithIdle(
        fuchsia::net::interfaces::Empty{}));
    // We should not have a pending callback already when setting initial state.
    CHECK(!pending_callback_);
  }

 private:
  void Watch(WatchCallback callback) override {
    ASSERT_FALSE(pending_callback_);
    if (pending_.empty()) {
      pending_callback_ = std::move(callback);
    } else {
      callback(std::move(pending_.front()));
      pending_.pop();
    }
  }

  void NotImplemented_(const std::string& name) override {
    LOG(FATAL) << "Unimplemented function called: " << name;
  }

  std::queue<fuchsia::net::interfaces::Event> pending_;
  fidl::Binding<fuchsia::net::interfaces::Watcher> binding_;
  WatchCallback pending_callback_ = nullptr;
};

class FakeWatcherAsync {
 public:
  FakeWatcherAsync() {
    base::Thread::Options options(base::MessagePumpType::IO, 0);
    CHECK(thread_.StartWithOptions(std::move(options)));
    watcher_ = base::SequenceBound<FakeWatcher>(thread_.task_runner());
  }
  FakeWatcherAsync(const FakeWatcherAsync&) = delete;
  FakeWatcherAsync& operator=(const FakeWatcherAsync&) = delete;
  ~FakeWatcherAsync() = default;

  void Bind(fidl::InterfaceRequest<fuchsia::net::interfaces::Watcher> request) {
    watcher_.AsyncCall(&FakeWatcher::Bind).WithArgs(std::move(request));
  }

  void Unbind() { watcher_.AsyncCall(&FakeWatcher::Unbind); }

  // Asynchronously push an event to the watcher.
  void PushEvent(fuchsia::net::interfaces::Event event) {
    watcher_.AsyncCall(&FakeWatcher::PushEvent).WithArgs(std::move(event));
  }

  // Asynchronously push an initial set of interfaces to the watcher.
  void SetInitial(std::vector<fuchsia::net::interfaces::Properties> props) {
    watcher_.AsyncCall(&FakeWatcher::SetInitial).WithArgs(std::move(props));
  }

  // Asynchronously push an initial single intface to the watcher.
  void SetInitial(fuchsia::net::interfaces::Properties prop) {
    SetInitial(MakeSingleItemVec(std::move(prop)));
  }

  // Ensures that any PushEvent() or SetInitial() calls have
  // been processed.
  void FlushThread() { thread_.FlushForTesting(); }

 private:
  base::Thread thread_{"Watcher Thread"};
  base::SequenceBound<FakeWatcher> watcher_;
};

template <class T>
class ResultReceiver {
 public:
  ~ResultReceiver() { EXPECT_EQ(entries_.size(), 0u); }
  bool RunAndExpectEntries(std::vector<T> expected_entries) {
    if (entries_.size() < expected_entries.size()) {
      base::RunLoop loop;
      base::AutoReset<size_t> size(&expected_count_, expected_entries.size());
      base::AutoReset<base::OnceClosure> quit(&quit_loop_, loop.QuitClosure());
      loop.Run();
    }
    return expected_entries == std::exchange(entries_, {});
  }
  void AddEntry(T entry) {
    entries_.push_back(entry);
    if (quit_loop_ && entries_.size() >= expected_count_)
      std::move(quit_loop_).Run();
  }

 protected:
  size_t expected_count_ = 0u;
  std::vector<T> entries_;
  base::OnceClosure quit_loop_;
};

// Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
class FakeConnectionTypeObserver final
    : public NetworkChangeNotifier::ConnectionTypeObserver {
 public:
  FakeConnectionTypeObserver() {
    NetworkChangeNotifier::AddConnectionTypeObserver(this);
  }
  ~FakeConnectionTypeObserver() override {
    NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
  }

  bool RunAndExpectConnectionTypes(
      std::vector<NetworkChangeNotifier::ConnectionType> sequence) {
    return receiver_.RunAndExpectEntries(sequence);
  }

  // ConnectionTypeObserver implementation.
  void OnConnectionTypeChanged(
      NetworkChangeNotifier::ConnectionType type) override {
    receiver_.AddEntry(type);
  }

 protected:
  ResultReceiver<NetworkChangeNotifier::ConnectionType> receiver_;
};

// Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
class FakeNetworkChangeObserver final
    : public NetworkChangeNotifier::NetworkChangeObserver {
 public:
  FakeNetworkChangeObserver() {
    NetworkChangeNotifier::AddNetworkChangeObserver(this);
  }
  ~FakeNetworkChangeObserver() override {
    NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
  }

  bool RunAndExpectNetworkChanges(
      std::vector<NetworkChangeNotifier::ConnectionType> sequence) {
    return receiver_.RunAndExpectEntries(sequence);
  }

  // NetworkChangeObserver implementation.
  void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override {
    receiver_.AddEntry(type);
  }

 protected:
  ResultReceiver<NetworkChangeNotifier::ConnectionType> receiver_;
};

// Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
class FakeIPAddressObserver final
    : public NetworkChangeNotifier::IPAddressObserver {
 public:
  FakeIPAddressObserver() { NetworkChangeNotifier::AddIPAddressObserver(this); }
  ~FakeIPAddressObserver() override {
    NetworkChangeNotifier::RemoveIPAddressObserver(this);
    EXPECT_EQ(ip_change_count_, 0u);
  }

  size_t ip_change_count() const { return ip_change_count_; }

  bool RunAndExpectCallCount(size_t expected_count) {
    if (ip_change_count_ < expected_count) {
      base::RunLoop loop;
      base::AutoReset<size_t> expectation(&expected_count_, expected_count);
      base::AutoReset<base::OnceClosure> quit(&quit_loop_, loop.QuitClosure());
      loop.Run();
    }
    return std::exchange(ip_change_count_, 0u) == expected_count;
  }

  // IPAddressObserver implementation.
  void OnIPAddressChanged() override {
    ip_change_count_++;
    if (quit_loop_ && ip_change_count_ >= expected_count_)
      std::move(quit_loop_).Run();
  }

 protected:
  size_t expected_count_ = 0u;
  size_t ip_change_count_ = 0u;
  base::OnceClosure quit_loop_;
};

}  // namespace

class NetworkChangeNotifierFuchsiaTest : public testing::Test {
 public:
  NetworkChangeNotifierFuchsiaTest() = default;
  NetworkChangeNotifierFuchsiaTest(const NetworkChangeNotifierFuchsiaTest&) =
      delete;
  NetworkChangeNotifierFuchsiaTest& operator=(
      const NetworkChangeNotifierFuchsiaTest&) = delete;
  ~NetworkChangeNotifierFuchsiaTest() override = default;

  // Creates a NetworkChangeNotifier that binds to |watcher_|.
  // |observer_| is registered last, so that tests need only express
  // expectations on changes they make themselves.
  void CreateNotifier(bool require_wlan = false,
                      bool disconnect_watcher = false) {
    // Ensure that internal state is up-to-date before the
    // notifier queries it.
    watcher_.FlushThread();

    fidl::InterfaceHandle<fuchsia::net::interfaces::Watcher> watcher;
    fidl::InterfaceRequest<fuchsia::net::interfaces::Watcher> watcher_request =
        watcher.NewRequest();
    if (disconnect_watcher) {
      // Reset the InterfaceRequest to close the `watcher` channel.
      watcher_request = {};
    } else {
      watcher_.Bind(std::move(watcher_request));
    }

    // Use a noop DNS notifier.
    dns_config_notifier_ = std::make_unique<SystemDnsConfigChangeNotifier>(
        nullptr /* task_runner */, nullptr /* dns_config_service */);
    notifier_ = base::WrapUnique(new NetworkChangeNotifierFuchsia(
        std::move(watcher), require_wlan, dns_config_notifier_.get()));

    type_observer_ = std::make_unique<FakeConnectionTypeObserver>();
    ip_observer_ = std::make_unique<FakeIPAddressObserver>();
  }

  void TearDown() override {
    // Spin the loops to catch any unintended notifications.
    watcher_.FlushThread();
    base::RunLoop().RunUntilIdle();
  }

 protected:
  base::test::SingleThreadTaskEnvironment task_environment_{
      base::test::SingleThreadTaskEnvironment::MainThreadType::IO};

  FakeWatcherAsync watcher_;

  // Allows us to allocate our own NetworkChangeNotifier for unit testing.
  NetworkChangeNotifier::DisableForTest disable_for_test_;
  std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier_;
  std::unique_ptr<NetworkChangeNotifierFuchsia> notifier_;

  std::unique_ptr<FakeConnectionTypeObserver> type_observer_;
  std::unique_ptr<FakeIPAddressObserver> ip_observer_;
};

TEST_F(NetworkChangeNotifierFuchsiaTest, ConnectFail_BeforeGetWatcher) {
  // CreateNotifier will pass an already-disconnected Watcher handle to the
  // new NetworkChangeNotifier, which will cause the process to exit during
  // construction.
  EXPECT_EXIT(
      CreateNotifier(/*require_wlan=*/false, /*disconnect_watcher=*/true),
      testing::ExitedWithCode(1), "");
}

TEST_F(NetworkChangeNotifierFuchsiaTest, ConnectFail_AfterGetWatcher) {
  CreateNotifier();

  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
            notifier_->GetCurrentConnectionType());

  // Disconnect the Watcher protocol in-use by the NetworkChangeNotifier.
  watcher_.Unbind();
  watcher_.FlushThread();

  // Spin the loop to process the disconnection, which should terminate the
  // test process.
  EXPECT_EXIT(base::RunLoop().RunUntilIdle(), testing::ExitedWithCode(1), "");

  // Teardown the notifier here to ensure it doesn't observe further events.
  notifier_ = nullptr;
}

TEST_F(NetworkChangeNotifierFuchsiaTest, InitialState) {
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
            notifier_->GetCurrentConnectionType());
}

TEST_F(NetworkChangeNotifierFuchsiaTest, InterfacesChangeDuringConstruction) {
  // Set a live interface with an IP address.
  watcher_.SetInitial(DefaultInterfaceProperties(
      fuchsia::hardware::network::DeviceClass::WLAN));

  // Inject an interfaces change event so that the notifier will receive it
  // immediately after the initial state.
  watcher_.PushEvent(MakeChangeEvent(
      kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
        props->set_addresses(MakeSingleItemVec(
            InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
      }));

  // Create the Notifier, which should process the initial network state before
  // returning, but not the change event, yet.
  CreateNotifier();
  EXPECT_EQ(ip_observer_->ip_change_count(), 0u);

  // Now spin the loop to allow the change event to be processed, triggering a
  // call to the |ip_observer_|.
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, NotifyNetworkChangeOnInitialIPChange) {
  // Set a live interface with an IP address and create the notifier.
  watcher_.SetInitial(DefaultInterfaceProperties(
      fuchsia::hardware::network::DeviceClass::WLAN));
  CreateNotifier();

  // Add the NetworkChangeNotifier, and change the IP address. This should
  // trigger a network change notification.
  FakeNetworkChangeObserver network_change_observer;

  watcher_.PushEvent(MakeChangeEvent(
      kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
        props->set_addresses(MakeSingleItemVec(
            InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
      }));

  EXPECT_TRUE(network_change_observer.RunAndExpectNetworkChanges(
      {NetworkChangeNotifier::CONNECTION_NONE,
       NetworkChangeNotifier::CONNECTION_WIFI}));
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, NoChange) {
  // Set a live interface with an IP address and create the notifier.
  watcher_.SetInitial(DefaultInterfaceProperties());
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
            notifier_->GetCurrentConnectionType());
  // Push an event with no side-effects.
  watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, NoChangeV6) {
  auto initial = DefaultInterfaceProperties();
  initial.set_addresses(MakeSingleItemVec(
      InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix)));
  watcher_.SetInitial(std::move(initial));
  CreateNotifier();
  // Push an event with no side-effects.
  watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, MultiInterfaceNoChange) {
  std::vector<fuchsia::net::interfaces::Properties> props;
  props.push_back(DefaultInterfaceProperties());
  props.push_back(SecondaryInterfaceProperties());
  watcher_.SetInitial(std::move(props));
  CreateNotifier();
  // Push an event with no side-effects.
  watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPNoChange) {
  auto props = DefaultInterfaceProperties();
  props.mutable_addresses()->push_back(
      InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix));
  props.mutable_addresses()->push_back(
      InterfaceAddressFrom(kSecondaryIPv6Address, kSecondaryIPv6Prefix));

  watcher_.SetInitial(std::move(props));
  CreateNotifier();

  // Push an event with no side-effects.
  watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, IpChange) {
  watcher_.SetInitial(DefaultInterfaceProperties());
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
            notifier_->GetCurrentConnectionType());

  watcher_.PushEvent(MakeChangeEvent(
      kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
        props->set_addresses(MakeSingleItemVec(
            InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
      }));

  // Expect a single OnIPAddressChanged() notification.
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, IpChangeV6) {
  auto props = DefaultInterfaceProperties();
  props.set_addresses(MakeSingleItemVec(
      InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix)));
  watcher_.SetInitial(std::move(props));
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
            notifier_->GetCurrentConnectionType());

  watcher_.PushEvent(MakeChangeEvent(
      kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
        props->set_addresses(MakeSingleItemVec(
            InterfaceAddressFrom(kSecondaryIPv6Address, kSecondaryIPv6Prefix)));
      }));

  // Expect a single OnIPAddressChanged() notification.
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPChanged) {
  auto props = DefaultInterfaceProperties();
  props.mutable_addresses()->push_back(
      InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix));

  watcher_.SetInitial(std::move(props));
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
            notifier_->GetCurrentConnectionType());

  watcher_.PushEvent(MakeChangeEvent(
      kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
        std::vector<fuchsia::net::interfaces::Address> addrs;
        addrs.push_back(
            InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix));
        addrs.push_back(
            InterfaceAddressFrom(kSecondaryIPv6Address, kSecondaryIPv6Prefix));
        props->set_addresses(std::move(addrs));
      }));

  // Expect a single OnIPAddressChanged() notification.
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, Ipv6AdditionalIpChange) {
  watcher_.SetInitial(DefaultInterfaceProperties());
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
            notifier_->GetCurrentConnectionType());

  watcher_.PushEvent(MakeChangeEvent(
      kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
        // Add the initial default address + a new IPv6 one. Address changes are
        // always sent as the entire new list of addresses.
        props->mutable_addresses()->push_back(
            InterfaceAddressFrom(kDefaultIPv4Address, kDefaultIPv4Prefix));
        props->mutable_addresses()->push_back(
            InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix));
      }));

  // Expect a single OnIPAddressChanged() notification.
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDown) {
  watcher_.SetInitial(DefaultInterfaceProperties());
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
            notifier_->GetCurrentConnectionType());

  watcher_.PushEvent(MakeChangeEvent(
      kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
        props->set_online(false);
      }));

  EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
      {NetworkChangeNotifier::ConnectionType::CONNECTION_NONE}));
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceUp) {
  auto props = DefaultInterfaceProperties();
  props.set_online(false);
  watcher_.SetInitial(std::move(props));
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
            notifier_->GetCurrentConnectionType());

  watcher_.PushEvent(MakeChangeEvent(
      kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
        props->set_online(true);
      }));

  EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
      {NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET}));
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDeleted) {
  watcher_.SetInitial(DefaultInterfaceProperties());
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
            notifier_->GetCurrentConnectionType());

  watcher_.PushEvent(
      fuchsia::net::interfaces::Event::WithRemoved(kDefaultInterfaceId));

  EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
      {NetworkChangeNotifier::ConnectionType::CONNECTION_NONE}));
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceAdded) {
  // Initial interface list is intentionally left empty.
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
            notifier_->GetCurrentConnectionType());

  watcher_.PushEvent(
      fuchsia::net::interfaces::Event::WithAdded(DefaultInterfaceProperties(
          fuchsia::hardware::network::DeviceClass::WLAN)));

  EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
      {NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI}));
  EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceAddedNoop) {
  watcher_.SetInitial(DefaultInterfaceProperties());
  CreateNotifier();

  watcher_.PushEvent(fuchsia::net::interfaces::Event::WithAdded(
      SecondaryInterfaceProperties()));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceDeletedNoop) {
  std::vector<fuchsia::net::interfaces::Properties> interfaces;
  interfaces.push_back(DefaultInterfaceProperties());
  interfaces.push_back(SecondaryInterfaceProperties());

  watcher_.SetInitial(std::move(interfaces));
  CreateNotifier();

  watcher_.PushEvent(
      fuchsia::net::interfaces::Event::WithRemoved(kSecondaryInterfaceId));
}

TEST_F(NetworkChangeNotifierFuchsiaTest, FoundWiFi) {
  watcher_.SetInitial(DefaultInterfaceProperties(
      fuchsia::hardware::network::DeviceClass::WLAN));
  CreateNotifier();
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
            notifier_->GetCurrentConnectionType());
}

TEST_F(NetworkChangeNotifierFuchsiaTest, FindsInterfaceWithRequiredWlan) {
  watcher_.SetInitial(DefaultInterfaceProperties(
      fuchsia::hardware::network::DeviceClass::WLAN));
  CreateNotifier(/*require_wlan=*/true);
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
            notifier_->GetCurrentConnectionType());
}

TEST_F(NetworkChangeNotifierFuchsiaTest, IgnoresNonWlanInterface) {
  watcher_.SetInitial(DefaultInterfaceProperties());
  CreateNotifier(/*require_wlan=*/true);
  EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
            notifier_->GetCurrentConnectionType());
}

}  // namespace net
