blob: feadbce0f29b9cb4d108319cbbd7416824cb951b [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/network_change_notifier_fuchsia.h"
#include <fuchsia/hardware/ethernet/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl_test_base.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/auto_reset.h"
#include "base/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/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 kIPv4DefaultGatewayNetmask = {0, 0, 0, 0};
constexpr IPv4Octets kIPv4DefaultGatewayAddress = {192, 168, 0, 1};
constexpr IPv4Octets kDefaultIPv4Address = {192, 168, 0, 2};
constexpr IPv4Octets kDefaultIPv4Netmask = {255, 255, 0, 0};
constexpr IPv4Octets kSecondaryIPv4Address = {10, 0, 0, 1};
constexpr IPv4Octets kSecondaryIPv4Netmask = {255, 0, 0, 0};
constexpr IPv6Octets kDefaultIPv6Address = {0xfe, 0x80, 0x01};
constexpr IPv6Octets kDefaultIPv6Netmask = {0xfe, 0x80};
constexpr IPv6Octets kSecondaryIPv6Address = {0xfe, 0x80, 0x02};
constexpr IPv6Octets kSecondaryIPv6Netmask = {0xfe, 0x80};
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;
}
fuchsia::net::Subnet SubnetFrom(IPv6Octets octets, uint8_t prefix) {
fuchsia::net::Subnet output;
output.addr = IpAddressFrom(octets);
output.prefix_len = prefix;
return output;
}
fuchsia::netstack::NetInterface DefaultNetInterface() {
// For most tests a live interface with an IPv4 address and no |features| set
// is sufficient.
fuchsia::netstack::NetInterface interface;
interface.id = kDefaultInterfaceId;
interface.flags = fuchsia::netstack::Flags::UP;
interface.features = {};
interface.addr = IpAddressFrom(kDefaultIPv4Address);
interface.netmask = IpAddressFrom(kDefaultIPv4Netmask);
interface.broadaddr = IpAddressFrom(kDefaultIPv4Address);
return interface;
}
fuchsia::netstack::NetInterface SecondaryNetInterface() {
// For most tests a live interface with an IPv4 address and no |features| set
// is sufficient.
fuchsia::netstack::NetInterface interface;
interface.id = kSecondaryInterfaceId;
interface.flags = fuchsia::netstack::Flags::UP;
interface.features = {};
interface.addr = IpAddressFrom(kSecondaryIPv4Address);
interface.netmask = IpAddressFrom(kSecondaryIPv4Netmask);
interface.broadaddr = IpAddressFrom(kSecondaryIPv4Address);
return interface;
}
std::vector<fuchsia::netstack::NetInterface> CloneNetInterfaces(
const std::vector<fuchsia::netstack::NetInterface>& interfaces) {
std::vector<fuchsia::netstack::NetInterface> interfaces_copy(
interfaces.size());
for (size_t i = 0; i < interfaces.size(); ++i) {
CHECK_EQ(ZX_OK, interfaces[i].Clone(&interfaces_copy[i]));
}
return interfaces_copy;
}
// Partial fake implementation of a Netstack.
class FakeNetstack : public fuchsia::netstack::testing::Netstack_TestBase {
public:
explicit FakeNetstack() : binding_(this) {}
~FakeNetstack() override = default;
void Bind(
fidl::InterfaceRequest<fuchsia::netstack::Netstack> netstack_request) {
CHECK_EQ(ZX_OK, binding_.Bind(std::move(netstack_request)));
binding_.events().OnInterfacesChanged(CloneNetInterfaces(interfaces_));
}
// Sets the interfaces reported by the fake Netstack and sends an
// OnInterfacesChanged() event to the client.
void SetInterfaces(std::vector<fuchsia::netstack::NetInterface> interfaces) {
interfaces_ = std::move(interfaces);
if (binding_.is_bound()) {
binding_.events().OnInterfacesChanged(CloneNetInterfaces(interfaces_));
}
}
private:
void GetRouteTable(GetRouteTableCallback callback) override {
CHECK(binding_.is_bound());
std::vector<fuchsia::netstack::RouteTableEntry> table(2);
table[0].nicid = kDefaultInterfaceId;
table[0].netmask = IpAddressFrom(kIPv4DefaultGatewayNetmask);
table[0].destination = IpAddressFrom(kDefaultIPv4Address);
table[0].gateway = IpAddressFrom(kIPv4DefaultGatewayAddress);
table[1].nicid = kSecondaryInterfaceId;
table[1].netmask = IpAddressFrom(kSecondaryIPv4Netmask);
table[1].destination = IpAddressFrom(kSecondaryIPv4Address);
table[1].gateway = IpAddressFrom(kSecondaryIPv4Address);
callback(std::move(table));
}
void NotImplemented_(const std::string& name) override {
LOG(FATAL) << "Unimplemented function called: " << name;
}
std::vector<fuchsia::netstack::NetInterface> interfaces_;
fidl::Binding<fuchsia::netstack::Netstack> binding_;
DISALLOW_COPY_AND_ASSIGN(FakeNetstack);
};
class FakeNetstackAsync {
public:
explicit FakeNetstackAsync() : thread_("Netstack Thread") {
base::Thread::Options options(base::MessagePumpType::IO, 0);
CHECK(thread_.StartWithOptions(options));
netstack_ = base::SequenceBound<FakeNetstack>(thread_.task_runner());
}
~FakeNetstackAsync() = default;
void Bind(
fidl::InterfaceRequest<fuchsia::netstack::Netstack> netstack_request) {
netstack_.Post(FROM_HERE, &FakeNetstack::Bind, std::move(netstack_request));
}
// Asynchronously update the state of the netstack.
void SetInterfaces(
const std::vector<fuchsia::netstack::NetInterface>& interfaces) {
netstack_.Post(FROM_HERE, &FakeNetstack::SetInterfaces,
CloneNetInterfaces(interfaces));
}
// Ensures that any SetInterfaces() or SendOnInterfacesChanged() calls have
// been processed.
void FlushNetstackThread() {
thread_.FlushForTesting();
}
private:
base::Thread thread_;
base::SequenceBound<FakeNetstack> netstack_;
DISALLOW_COPY_AND_ASSIGN(FakeNetstackAsync);
};
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
: public NetworkChangeNotifier::ConnectionTypeObserver {
public:
FakeConnectionTypeObserver() {
NetworkChangeNotifier::AddConnectionTypeObserver(this);
}
~FakeConnectionTypeObserver() final {
NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
}
bool RunAndExpectConnectionTypes(
std::vector<NetworkChangeNotifier::ConnectionType> sequence) {
return receiver_.RunAndExpectEntries(sequence);
}
// ConnectionTypeObserver implementation.
void OnConnectionTypeChanged(
NetworkChangeNotifier::ConnectionType type) final {
receiver_.AddEntry(type);
}
protected:
ResultReceiver<NetworkChangeNotifier::ConnectionType> receiver_;
};
// Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
class FakeNetworkChangeObserver
: public NetworkChangeNotifier::NetworkChangeObserver {
public:
FakeNetworkChangeObserver() {
NetworkChangeNotifier::AddNetworkChangeObserver(this);
}
~FakeNetworkChangeObserver() final {
NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
}
bool RunAndExpectNetworkChanges(
std::vector<NetworkChangeNotifier::ConnectionType> sequence) {
return receiver_.RunAndExpectEntries(sequence);
}
// NetworkChangeObserver implementation.
void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) final {
receiver_.AddEntry(type);
}
protected:
ResultReceiver<NetworkChangeNotifier::ConnectionType> receiver_;
};
// Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
class FakeIPAddressObserver : public NetworkChangeNotifier::IPAddressObserver {
public:
FakeIPAddressObserver() { NetworkChangeNotifier::AddIPAddressObserver(this); }
~FakeIPAddressObserver() final {
NetworkChangeNotifier::RemoveIPAddressObserver(this);
EXPECT_EQ(ip_change_count_, 0u);
}
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() final {
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() {}
~NetworkChangeNotifierFuchsiaTest() override = default;
// Creates a NetworkChangeNotifier and spins the MessageLoop to allow it to
// populate from the list of interfaces which have already been added to
// |netstack_|. |observer_| is registered last, so that tests need only
// express expectations on changes they make themselves.
void CreateNotifier(
fuchsia::hardware::ethernet::Features required_features = {}) {
// Ensure that the Netstack internal state is up-to-date before the
// notifier queries it.
netstack_.FlushNetstackThread();
CHECK(!netstack_handle_);
netstack_.Bind(netstack_handle_.NewRequest());
// Use a noop DNS notifier.
dns_config_notifier_ = std::make_unique<SystemDnsConfigChangeNotifier>(
nullptr /* task_runner */, nullptr /* dns_config_service */);
notifier_.reset(new NetworkChangeNotifierFuchsia(
std::move(netstack_handle_), required_features,
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.
netstack_.FlushNetstackThread();
base::RunLoop().RunUntilIdle();
}
protected:
base::test::SingleThreadTaskEnvironment task_environment_{
base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
fidl::InterfaceHandle<fuchsia::netstack::Netstack> netstack_handle_;
FakeNetstackAsync netstack_;
// 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_;
private:
DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierFuchsiaTest);
};
TEST_F(NetworkChangeNotifierFuchsiaTest, InitialState) {
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
notifier_->GetCurrentConnectionType());
}
TEST_F(NetworkChangeNotifierFuchsiaTest, NotifyNetworkChangeOnInitialIPChange) {
// Set a live interface with an IP address and create the notifier.
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].features = fuchsia::hardware::ethernet::Features::WLAN;
netstack_.SetInterfaces(interfaces);
CreateNotifier();
// Add the NetworkChangeNotifier, and change the IP address. This should
// trigger a network change notification, since the IP address is out-of-sync.
FakeNetworkChangeObserver network_change_observer;
interfaces[0].addr = IpAddressFrom(kSecondaryIPv4Address);
netstack_.SetInterfaces(interfaces);
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.
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
// Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
netstack_.SetInterfaces(interfaces);
}
TEST_F(NetworkChangeNotifierFuchsiaTest, NoChangeV6) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].addr = IpAddressFrom(kDefaultIPv6Address);
interfaces[0].netmask = IpAddressFrom(kDefaultIPv6Netmask);
netstack_.SetInterfaces(interfaces);
CreateNotifier();
// Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
netstack_.SetInterfaces(interfaces);
}
TEST_F(NetworkChangeNotifierFuchsiaTest, MultiInterfaceNoChange) {
std::vector<fuchsia::netstack::NetInterface> interfaces(2);
interfaces[0] = DefaultNetInterface();
interfaces[1] = SecondaryNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier();
// Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
netstack_.SetInterfaces(interfaces);
}
TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPNoChange) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].ipv6addrs.push_back(SubnetFrom(kDefaultIPv6Address, 2));
netstack_.SetInterfaces(interfaces);
CreateNotifier();
// Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
netstack_.SetInterfaces(interfaces);
}
TEST_F(NetworkChangeNotifierFuchsiaTest, IpChange) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].addr = IpAddressFrom(kSecondaryIPv4Address);
netstack_.SetInterfaces(interfaces);
// Expect a single OnIPAddressChanged() notification.
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, IpChangeV6) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].addr = IpAddressFrom(kDefaultIPv6Address);
interfaces[0].netmask = IpAddressFrom(kDefaultIPv6Netmask);
interfaces[0].broadaddr = IpAddressFrom(kDefaultIPv6Address);
netstack_.SetInterfaces(interfaces);
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].addr = IpAddressFrom(kSecondaryIPv6Address);
interfaces[0].netmask = IpAddressFrom(kSecondaryIPv6Netmask);
interfaces[0].broadaddr = IpAddressFrom(kSecondaryIPv6Address);
netstack_.SetInterfaces(interfaces);
// Expect a single OnIPAddressChanged() notification.
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPChanged) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].ipv6addrs.push_back(SubnetFrom(kDefaultIPv6Address, 2));
netstack_.SetInterfaces(interfaces);
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].addr = IpAddressFrom(kSecondaryIPv4Address);
interfaces[0].netmask = IpAddressFrom(kSecondaryIPv4Netmask);
interfaces[0].broadaddr = IpAddressFrom(kSecondaryIPv4Address);
interfaces[0].ipv6addrs[0] = SubnetFrom(kSecondaryIPv6Address, 2);
netstack_.SetInterfaces(interfaces);
// Expect a single OnIPAddressChanged() notification.
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, Ipv6AdditionalIpChange) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].ipv6addrs.push_back(SubnetFrom(kDefaultIPv6Address, 2));
netstack_.SetInterfaces(interfaces);
// Expect a single OnIPAddressChanged() notification.
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDown) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].flags = {};
netstack_.SetInterfaces(interfaces);
EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_NONE}));
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceUp) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].flags = {};
netstack_.SetInterfaces(interfaces);
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
notifier_->GetCurrentConnectionType());
interfaces[0].flags = fuchsia::netstack::Flags::UP;
netstack_.SetInterfaces(interfaces);
EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN}));
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDeleted) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
netstack_.SetInterfaces({});
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());
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].features = fuchsia::hardware::ethernet::Features::WLAN;
netstack_.SetInterfaces(interfaces);
EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI}));
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceAddedNoop) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier();
interfaces.push_back(SecondaryNetInterface());
netstack_.SetInterfaces(interfaces);
}
TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceDeletedNoop) {
std::vector<fuchsia::netstack::NetInterface> interfaces(2);
interfaces[0] = DefaultNetInterface();
interfaces[1] = SecondaryNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier();
interfaces.pop_back();
netstack_.SetInterfaces(interfaces);
}
TEST_F(NetworkChangeNotifierFuchsiaTest, FoundWiFi) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].features = fuchsia::hardware::ethernet::Features::WLAN;
netstack_.SetInterfaces(interfaces);
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
notifier_->GetCurrentConnectionType());
}
TEST_F(NetworkChangeNotifierFuchsiaTest, FindsInterfaceWithRequiredFeature) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].features = fuchsia::hardware::ethernet::Features::WLAN;
netstack_.SetInterfaces(interfaces);
CreateNotifier(fuchsia::hardware::ethernet::Features::WLAN);
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
notifier_->GetCurrentConnectionType());
}
TEST_F(NetworkChangeNotifierFuchsiaTest, IgnoresInterfaceWithMissingFeature) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier(fuchsia::hardware::ethernet::Features::WLAN);
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
notifier_->GetCurrentConnectionType());
}
} // namespace net