Commit 76b8a9bf authored by Wez's avatar Wez Committed by Commit Bot

[fuchsia] Fix NetworkChangeNotifierFuchsia test.

This test made assumptions regarding the timely processing of network-
change notifications, resulting in flakiness.

Fix the test to explicitly wait on each expected OnNetworkChanged()
notification before continuing.

Bug: 1064673, b/142796913
Change-Id: I9da235476415274ebcd254d8f6d08a62176b31c7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2124669
Commit-Queue: Wez <wez@chromium.org>
Reviewed-by: default avatarSergey Ulanov <sergeyu@chromium.org>
Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Auto-Submit: Wez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756991}
parent 2fd97a3d
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/auto_reset.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
...@@ -24,77 +25,77 @@ ...@@ -24,77 +25,77 @@
namespace net { namespace net {
namespace { namespace {
const int kDefaultNic = 1; enum : uint32_t { kDefaultInterfaceId = 1, kSecondaryInterfaceId = 2 };
const int kSecondaryNic = kDefaultNic + 1;
fuchsia::net::IpAddress CreateIPv6Address(std::vector<uint8_t> addr) { 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; fuchsia::net::IpAddress output;
for (size_t i = 0; i < addr.size(); ++i) { output.ipv4().addr = octets;
output.ipv6().addr[i] = addr[i];
}
return output; return output;
} }
fuchsia::net::Subnet CreateSubnet(const std::vector<uint8_t>& addr, fuchsia::net::IpAddress IpAddressFrom(IPv6Octets octets) {
uint8_t prefix) { fuchsia::net::IpAddress output;
fuchsia::net::Subnet output; output.ipv6().addr = octets;
output.addr = CreateIPv6Address(addr);
output.prefix_len = prefix;
return output; return output;
} }
fuchsia::net::IpAddress CreateIPv4Address(uint8_t a0, fuchsia::net::Subnet SubnetFrom(IPv6Octets octets, uint8_t prefix) {
uint8_t a1, fuchsia::net::Subnet output;
uint8_t a2, output.addr = IpAddressFrom(octets);
uint8_t a3) { output.prefix_len = prefix;
fuchsia::net::IpAddress output;
output.ipv4().addr[0] = a0;
output.ipv4().addr[1] = a1;
output.ipv4().addr[2] = a2;
output.ipv4().addr[3] = a3;
return output; return output;
} }
fuchsia::netstack::RouteTableEntry CreateRouteTableEntry(uint32_t nicid, fuchsia::netstack::NetInterface DefaultNetInterface() {
bool is_default) { // For most tests a live interface with an IPv4 address and no |features| set
fuchsia::netstack::RouteTableEntry output; // is sufficient.
output.nicid = nicid; fuchsia::netstack::NetInterface interface;
interface.id = kDefaultInterfaceId;
if (is_default) { interface.flags = fuchsia::netstack::NetInterfaceFlagUp;
output.netmask = CreateIPv4Address(0, 0, 0, 0); interface.features = 0;
output.destination = CreateIPv4Address(192, 168, 42, 0); interface.addr = IpAddressFrom(kDefaultIPv4Address);
output.gateway = CreateIPv4Address(192, 168, 42, 1); interface.netmask = IpAddressFrom(kDefaultIPv4Netmask);
} else { interface.broadaddr = IpAddressFrom(kDefaultIPv4Address);
output.netmask = CreateIPv4Address(255, 255, 255, 0); return interface;
output.destination = CreateIPv4Address(192, 168, 43, 0); }
output.gateway = CreateIPv4Address(192, 168, 43, 1);
}
return output; 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::NetInterfaceFlagUp;
interface.features = 0;
interface.addr = IpAddressFrom(kSecondaryIPv4Address);
interface.netmask = IpAddressFrom(kSecondaryIPv4Netmask);
interface.broadaddr = IpAddressFrom(kSecondaryIPv4Address);
return interface;
} }
fuchsia::netstack::NetInterface CreateNetInterface( std::vector<fuchsia::netstack::NetInterface> CloneNetInterfaces(
uint32_t id, const std::vector<fuchsia::netstack::NetInterface>& interfaces) {
uint32_t flags, std::vector<fuchsia::netstack::NetInterface> interfaces_copy(
uint32_t features, interfaces.size());
fuchsia::net::IpAddress address, for (size_t i = 0; i < interfaces.size(); ++i) {
fuchsia::net::IpAddress netmask, CHECK_EQ(ZX_OK, interfaces[i].Clone(&interfaces_copy[i]));
std::vector<fuchsia::net::Subnet> ipv6) {
fuchsia::netstack::NetInterface output;
output.name = "foo";
output.id = id;
output.flags = flags;
output.features = features;
output.addr = std::move(address);
output.netmask = std::move(netmask);
output.addr.Clone(&output.broadaddr);
for (auto& x : ipv6) {
output.ipv6addrs.push_back(std::move(x));
} }
return interfaces_copy;
return output;
} }
// Partial fake implementation of a Netstack. // Partial fake implementation of a Netstack.
...@@ -107,34 +108,32 @@ class FakeNetstack : public fuchsia::netstack::testing::Netstack_TestBase { ...@@ -107,34 +108,32 @@ class FakeNetstack : public fuchsia::netstack::testing::Netstack_TestBase {
} }
~FakeNetstack() override = default; ~FakeNetstack() override = default;
// Adds |interface| to the interface query response list. // Sets the interfaces reported by the fake Netstack and sends an
void PushInterface(fuchsia::netstack::NetInterface interface) { // OnInterfacesChanged() event to the client.
interfaces_.push_back(std::move(interface)); void SetInterfaces(std::vector<fuchsia::netstack::NetInterface> interfaces) {
} interfaces_ = std::move(interfaces);
binding_.events().OnInterfacesChanged(CloneNetInterfaces(interfaces_));
// Sends the accumulated |interfaces_| to the OnInterfacesChanged event.
void NotifyInterfaces() {
binding_.events().OnInterfacesChanged(std::move(interfaces_));
interfaces_.clear();
}
void SetOnGetRouteTableCallback(base::OnceClosure callback) {
on_get_route_table_ = std::move(callback);
} }
private: private:
void GetInterfaces(GetInterfacesCallback callback) override { void GetInterfaces(GetInterfacesCallback callback) override {
callback(std::move(interfaces_)); callback(CloneNetInterfaces(interfaces_));
} }
void GetRouteTable(GetRouteTableCallback callback) override { void GetRouteTable(GetRouteTableCallback callback) override {
std::vector<fuchsia::netstack::RouteTableEntry> table(2); std::vector<fuchsia::netstack::RouteTableEntry> table(2);
table[0] = CreateRouteTableEntry(kDefaultNic, true);
table[1] = CreateRouteTableEntry(kSecondaryNic, false);
callback(std::move(table));
if (on_get_route_table_) table[0].nicid = kDefaultInterfaceId;
std::move(on_get_route_table_).Run(); 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 { void NotImplemented_(const std::string& name) override {
...@@ -142,11 +141,8 @@ class FakeNetstack : public fuchsia::netstack::testing::Netstack_TestBase { ...@@ -142,11 +141,8 @@ class FakeNetstack : public fuchsia::netstack::testing::Netstack_TestBase {
} }
std::vector<fuchsia::netstack::NetInterface> interfaces_; std::vector<fuchsia::netstack::NetInterface> interfaces_;
fidl::Binding<fuchsia::netstack::Netstack> binding_; fidl::Binding<fuchsia::netstack::Netstack> binding_;
base::OnceClosure on_get_route_table_;
DISALLOW_COPY_AND_ASSIGN(FakeNetstack); DISALLOW_COPY_AND_ASSIGN(FakeNetstack);
}; };
...@@ -163,22 +159,15 @@ class FakeNetstackAsync { ...@@ -163,22 +159,15 @@ class FakeNetstackAsync {
~FakeNetstackAsync() = default; ~FakeNetstackAsync() = default;
// Asynchronously update the state of the netstack. // Asynchronously update the state of the netstack.
void PushInterface(fuchsia::netstack::NetInterface interface) { void SetInterfaces(
netstack_.Post(FROM_HERE, &FakeNetstack::PushInterface, const std::vector<fuchsia::netstack::NetInterface>& interfaces) {
std::move(interface)); netstack_.Post(FROM_HERE, &FakeNetstack::SetInterfaces,
} CloneNetInterfaces(interfaces));
void NotifyInterfaces() {
netstack_.Post(FROM_HERE, &FakeNetstack::NotifyInterfaces);
}
void SetOnGetRouteTableCallback(base::OnceClosure callback) {
netstack_.Post(FROM_HERE, &FakeNetstack::SetOnGetRouteTableCallback,
std::move(callback));
} }
// Ensure that any PushInterface() or NotifyInterfaces() have been processed. // Ensures that any SetInterfaces() or SendOnInterfacesChanged() calls have
// been processed.
void FlushNetstackThread() { void FlushNetstackThread() {
// Ensure that pending Push*() and Notify*() calls were processed.
thread_.FlushForTesting(); thread_.FlushForTesting();
} }
...@@ -189,22 +178,112 @@ class FakeNetstackAsync { ...@@ -189,22 +178,112 @@ class FakeNetstackAsync {
DISALLOW_COPY_AND_ASSIGN(FakeNetstackAsync); DISALLOW_COPY_AND_ASSIGN(FakeNetstackAsync);
}; };
class MockConnectionTypeObserver template <class T>
: public NetworkChangeNotifier::ConnectionTypeObserver { class ResultReceiver {
public: public:
MOCK_METHOD1(OnConnectionTypeChanged, ~ResultReceiver() { EXPECT_EQ(entries_.size(), 0u); }
void(NetworkChangeNotifier::ConnectionType)); 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_;
}; };
class MockIPAddressObserver : public NetworkChangeNotifier::IPAddressObserver { // Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
class FakeConnectionTypeObserver
: public NetworkChangeNotifier::ConnectionTypeObserver {
public: public:
MOCK_METHOD0(OnIPAddressChanged, void()); 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_;
}; };
class MockNetworkChangeObserver // Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
class FakeNetworkChangeObserver
: public NetworkChangeNotifier::NetworkChangeObserver { : public NetworkChangeNotifier::NetworkChangeObserver {
public: public:
MOCK_METHOD1(OnNetworkChanged, void(NetworkChangeNotifier::ConnectionType)); 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 } // namespace
...@@ -230,35 +309,19 @@ class NetworkChangeNotifierFuchsiaTest : public testing::Test { ...@@ -230,35 +309,19 @@ class NetworkChangeNotifierFuchsiaTest : public testing::Test {
std::move(netstack_ptr_), required_features, std::move(netstack_ptr_), required_features,
dns_config_notifier_.get())); dns_config_notifier_.get()));
NetworkChangeNotifier::AddConnectionTypeObserver(&observer_); type_observer_ = std::make_unique<FakeConnectionTypeObserver>();
NetworkChangeNotifier::AddIPAddressObserver(&ip_observer_); ip_observer_ = std::make_unique<FakeIPAddressObserver>();
} }
void TearDown() override { void TearDown() override {
// Spin the loops to catch any unintended notifications. // Spin the loops to catch any unintended notifications.
netstack_.FlushNetstackThread(); netstack_.FlushNetstackThread();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
if (notifier_) {
NetworkChangeNotifier::RemoveConnectionTypeObserver(&observer_);
NetworkChangeNotifier::RemoveIPAddressObserver(&ip_observer_);
}
}
// Causes FakeNetstack to emit NotifyInterfaces(), and then runs the loop
// until the GetRouteTable() is called.
void NetstackNotifyInterfacesAndWaitForGetRouteTable() {
base::RunLoop loop;
netstack_.SetOnGetRouteTableCallback(loop.QuitClosure());
netstack_.NotifyInterfaces();
loop.Run();
} }
protected: protected:
base::test::SingleThreadTaskEnvironment task_environment_{ base::test::SingleThreadTaskEnvironment task_environment_{
base::test::SingleThreadTaskEnvironment::MainThreadType::IO}; base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
testing::StrictMock<MockConnectionTypeObserver> observer_;
testing::StrictMock<MockIPAddressObserver> ip_observer_;
fuchsia::netstack::NetstackPtr netstack_ptr_; fuchsia::netstack::NetstackPtr netstack_ptr_;
FakeNetstackAsync netstack_; FakeNetstackAsync netstack_;
...@@ -268,6 +331,9 @@ class NetworkChangeNotifierFuchsiaTest : public testing::Test { ...@@ -268,6 +331,9 @@ class NetworkChangeNotifierFuchsiaTest : public testing::Test {
std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier_; std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier_;
std::unique_ptr<NetworkChangeNotifierFuchsia> notifier_; std::unique_ptr<NetworkChangeNotifierFuchsia> notifier_;
std::unique_ptr<FakeConnectionTypeObserver> type_observer_;
std::unique_ptr<FakeIPAddressObserver> ip_observer_;
private: private:
DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierFuchsiaTest); DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierFuchsiaTest);
}; };
...@@ -279,337 +345,269 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, InitialState) { ...@@ -279,337 +345,269 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, InitialState) {
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, NotifyNetworkChangeOnInitialIPChange) { TEST_F(NetworkChangeNotifierFuchsiaTest, NotifyNetworkChangeOnInitialIPChange) {
// Set up expectations on the IPAddressObserver, and attach a mock // Set a live interface with an IP address and create the notifier.
// NetworkChangeObserver. std::vector<fuchsia::netstack::NetInterface> interfaces(1);
testing::StrictMock<MockNetworkChangeObserver> network_change_observer; interfaces[0] = DefaultNetInterface();
{ interfaces[0].features = fuchsia::hardware::ethernet::INFO_FEATURE_WLAN;
testing::InSequence seq;
EXPECT_CALL(network_change_observer, netstack_.SetInterfaces(interfaces);
OnNetworkChanged(NetworkChangeNotifier::CONNECTION_NONE));
EXPECT_CALL(network_change_observer,
OnNetworkChanged(NetworkChangeNotifier::CONNECTION_WIFI));
}
EXPECT_CALL(ip_observer_, OnIPAddressChanged());
// Set an initial IP address and create the notifier.
netstack_.PushInterface(
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp,
fuchsia::hardware::ethernet::INFO_FEATURE_WLAN,
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
CreateNotifier(); CreateNotifier();
// Add the NetworkChangeNotifier, and change the IP address. This should // Add the NetworkChangeNotifier, and change the IP address. This should
// trigger a network change notification, since the IP address is out-of-sync. // trigger a network change notification, since the IP address is out-of-sync.
NetworkChangeNotifier::AddNetworkChangeObserver(&network_change_observer); FakeNetworkChangeObserver network_change_observer;
netstack_.PushInterface(CreateNetInterface( interfaces[0].addr = IpAddressFrom(kSecondaryIPv4Address);
kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, netstack_.SetInterfaces(interfaces);
fuchsia::hardware::ethernet::INFO_FEATURE_WLAN,
CreateIPv4Address(10, 0, 0, 1), CreateIPv4Address(255, 255, 0, 0), {}));
NetstackNotifyInterfacesAndWaitForGetRouteTable();
NetworkChangeNotifier::RemoveNetworkChangeObserver(&network_change_observer); EXPECT_TRUE(network_change_observer.RunAndExpectNetworkChanges(
{NetworkChangeNotifier::CONNECTION_NONE,
NetworkChangeNotifier::CONNECTION_WIFI}));
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, NoChange) { TEST_F(NetworkChangeNotifierFuchsiaTest, NoChange) {
netstack_.PushInterface( // Set a live interface with an IP address and create the notifier.
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, std::vector<fuchsia::netstack::NetInterface> interfaces(1);
CreateIPv4Address(169, 254, 0, 1), interfaces[0] = DefaultNetInterface();
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.SetInterfaces(interfaces);
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
netstack_.PushInterface( // Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, netstack_.SetInterfaces(interfaces);
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.NotifyInterfaces();
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, NoChangeV6) { TEST_F(NetworkChangeNotifierFuchsiaTest, NoChangeV6) {
netstack_.PushInterface( std::vector<fuchsia::netstack::NetInterface> interfaces(1);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, interfaces[0] = DefaultNetInterface();
CreateIPv6Address({0xfe, 0x80, 0x01}), interfaces[0].addr = IpAddressFrom(kDefaultIPv6Address);
CreateIPv6Address({0xfe, 0x80}), {})); interfaces[0].netmask = IpAddressFrom(kDefaultIPv6Netmask);
netstack_.SetInterfaces(interfaces);
CreateNotifier(); CreateNotifier();
netstack_.PushInterface( // Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, netstack_.SetInterfaces(interfaces);
CreateIPv6Address({0xfe, 0x80, 0x01}),
CreateIPv6Address({0xfe, 0x80}), {}));
netstack_.NotifyInterfaces();
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, MultiInterfaceNoChange) { TEST_F(NetworkChangeNotifierFuchsiaTest, MultiInterfaceNoChange) {
netstack_.PushInterface( std::vector<fuchsia::netstack::NetInterface> interfaces(2);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, interfaces[0] = DefaultNetInterface();
CreateIPv4Address(169, 254, 0, 1), interfaces[1] = SecondaryNetInterface();
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.PushInterface( netstack_.SetInterfaces(interfaces);
CreateNetInterface(kSecondaryNic, fuchsia::netstack::NetInterfaceFlagUp,
0, CreateIPv4Address(169, 254, 0, 2),
CreateIPv4Address(255, 255, 255, 0), {}));
CreateNotifier(); CreateNotifier();
netstack_.PushInterface( // Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, netstack_.SetInterfaces(interfaces);
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.PushInterface(
CreateNetInterface(kSecondaryNic, fuchsia::netstack::NetInterfaceFlagUp,
0, CreateIPv4Address(169, 254, 0, 3),
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.NotifyInterfaces();
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPNoChange) { TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPNoChange) {
std::vector<fuchsia::net::Subnet> addresses; std::vector<fuchsia::netstack::NetInterface> interfaces(1);
addresses.push_back(CreateSubnet({0xfe, 0x80, 0x01}, 2)); interfaces[0] = DefaultNetInterface();
netstack_.PushInterface(CreateNetInterface( interfaces[0].ipv6addrs.push_back(SubnetFrom(kDefaultIPv6Address, 2));
kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv4Address(169, 254, 0, 1), CreateIPv4Address(255, 255, 255, 0),
std::move(addresses)));
netstack_.SetInterfaces(interfaces);
CreateNotifier(); CreateNotifier();
addresses.push_back(CreateSubnet({0xfe, 0x80, 0x01}, 2)); // Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
netstack_.PushInterface(CreateNetInterface( netstack_.SetInterfaces(interfaces);
kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv4Address(169, 254, 0, 1), CreateIPv4Address(255, 255, 255, 0),
std::move(addresses)));
netstack_.NotifyInterfaces();
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, IpChange) { TEST_F(NetworkChangeNotifierFuchsiaTest, IpChange) {
EXPECT_CALL(ip_observer_, OnIPAddressChanged()); std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.PushInterface( netstack_.SetInterfaces(interfaces);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
netstack_.PushInterface(CreateNetInterface( interfaces[0].addr = IpAddressFrom(kSecondaryIPv4Address);
kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, netstack_.SetInterfaces(interfaces);
CreateIPv4Address(10, 0, 0, 1), CreateIPv4Address(255, 255, 0, 0), {}));
NetstackNotifyInterfacesAndWaitForGetRouteTable(); // Expect a single OnIPAddressChanged() notification.
ip_observer_->RunAndExpectCallCount(1);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, IpChangeV6) { TEST_F(NetworkChangeNotifierFuchsiaTest, IpChangeV6) {
EXPECT_CALL(ip_observer_, OnIPAddressChanged()); 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_.PushInterface( netstack_.SetInterfaces(interfaces);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv6Address({0xfe, 0x80, 0x01}),
CreateIPv6Address({0xfe, 0x80}), {}));
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
netstack_.PushInterface( interfaces[0].addr = IpAddressFrom(kSecondaryIPv6Address);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, interfaces[0].netmask = IpAddressFrom(kSecondaryIPv6Netmask);
CreateIPv6Address({0xfe, 0x80, 0x02}), interfaces[0].broadaddr = IpAddressFrom(kSecondaryIPv6Address);
CreateIPv6Address({0xfe, 0x80}), {})); netstack_.SetInterfaces(interfaces);
NetstackNotifyInterfacesAndWaitForGetRouteTable(); // Expect a single OnIPAddressChanged() notification.
ip_observer_->RunAndExpectCallCount(1);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPChanged) { TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPChanged) {
EXPECT_CALL(ip_observer_, OnIPAddressChanged()); std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
std::vector<fuchsia::net::Subnet> addresses; interfaces[0].ipv6addrs.push_back(SubnetFrom(kDefaultIPv6Address, 2));
addresses.push_back(CreateSubnet({0xfe, 0x80, 0x01}, 2));
netstack_.PushInterface(CreateNetInterface(
kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv4Address(169, 254, 0, 1), CreateIPv4Address(255, 255, 255, 0),
std::move(addresses)));
netstack_.SetInterfaces(interfaces);
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
addresses.push_back(CreateSubnet({0xfe, 0x80, 0x02}, 2)); interfaces[0].addr = IpAddressFrom(kSecondaryIPv4Address);
netstack_.PushInterface(CreateNetInterface( interfaces[0].netmask = IpAddressFrom(kSecondaryIPv4Netmask);
kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, interfaces[0].broadaddr = IpAddressFrom(kSecondaryIPv4Address);
CreateIPv4Address(10, 0, 0, 1), CreateIPv4Address(255, 255, 0, 0), interfaces[0].ipv6addrs[0] = SubnetFrom(kSecondaryIPv6Address, 2);
std::move(addresses))); netstack_.SetInterfaces(interfaces);
NetstackNotifyInterfacesAndWaitForGetRouteTable(); // Expect a single OnIPAddressChanged() notification.
ip_observer_->RunAndExpectCallCount(1);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, Ipv6AdditionalIpChange) { TEST_F(NetworkChangeNotifierFuchsiaTest, Ipv6AdditionalIpChange) {
EXPECT_CALL(ip_observer_, OnIPAddressChanged()); std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.PushInterface(
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.SetInterfaces(interfaces);
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
std::vector<fuchsia::net::Subnet> addresses; interfaces[0].ipv6addrs.push_back(SubnetFrom(kDefaultIPv6Address, 2));
addresses.push_back(CreateSubnet({0xfe, 0x80, 0x01}, 2)); netstack_.SetInterfaces(interfaces);
netstack_.PushInterface(CreateNetInterface(
kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv4Address(169, 254, 0, 1), CreateIPv4Address(255, 255, 255, 0),
std::move(addresses)));
NetstackNotifyInterfacesAndWaitForGetRouteTable(); // Expect a single OnIPAddressChanged() notification.
ip_observer_->RunAndExpectCallCount(1);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDown) { TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDown) {
EXPECT_CALL(ip_observer_, OnIPAddressChanged()); std::vector<fuchsia::netstack::NetInterface> interfaces(1);
EXPECT_CALL(observer_, interfaces[0] = DefaultNetInterface();
OnConnectionTypeChanged(NetworkChangeNotifier::CONNECTION_NONE));
netstack_.PushInterface(
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.SetInterfaces(interfaces);
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
netstack_.PushInterface( interfaces[0].flags = 0;
CreateNetInterface(1, 0, 0, CreateIPv4Address(169, 254, 0, 1), netstack_.SetInterfaces(interfaces);
CreateIPv4Address(255, 255, 0, 0), {}));
NetstackNotifyInterfacesAndWaitForGetRouteTable(); type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_NONE});
ip_observer_->RunAndExpectCallCount(1);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceUp) { TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceUp) {
EXPECT_CALL(ip_observer_, OnIPAddressChanged()); std::vector<fuchsia::netstack::NetInterface> interfaces(1);
EXPECT_CALL(observer_, OnConnectionTypeChanged( interfaces[0] = DefaultNetInterface();
NetworkChangeNotifier::CONNECTION_UNKNOWN)); interfaces[0].flags = 0;
netstack_.PushInterface(
CreateNetInterface(1, 0, 0, CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.SetInterfaces(interfaces);
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
netstack_.PushInterface( interfaces[0].flags = fuchsia::netstack::NetInterfaceFlagUp;
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, netstack_.SetInterfaces(interfaces);
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 0, 0), {}));
NetstackNotifyInterfacesAndWaitForGetRouteTable(); type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN});
ip_observer_->RunAndExpectCallCount(1);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDeleted) { TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDeleted) {
EXPECT_CALL(ip_observer_, OnIPAddressChanged()); std::vector<fuchsia::netstack::NetInterface> interfaces(1);
EXPECT_CALL(observer_, interfaces[0] = DefaultNetInterface();
OnConnectionTypeChanged(NetworkChangeNotifier::CONNECTION_NONE));
netstack_.SetInterfaces(interfaces);
netstack_.PushInterface(
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
// NotifyInterfaces() with no new PushInterfaces() means removing everything. netstack_.SetInterfaces({});
NetstackNotifyInterfacesAndWaitForGetRouteTable();
type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_NONE});
ip_observer_->RunAndExpectCallCount(1);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceAdded) { TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceAdded) {
EXPECT_CALL(ip_observer_, OnIPAddressChanged());
EXPECT_CALL(observer_,
OnConnectionTypeChanged(NetworkChangeNotifier::CONNECTION_WIFI));
// Initial interface list is intentionally left empty. // Initial interface list is intentionally left empty.
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
netstack_.PushInterface( std::vector<fuchsia::netstack::NetInterface> interfaces(1);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, interfaces[0] = DefaultNetInterface();
fuchsia::hardware::ethernet::INFO_FEATURE_WLAN, interfaces[0].features = fuchsia::hardware::ethernet::INFO_FEATURE_WLAN;
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
NetstackNotifyInterfacesAndWaitForGetRouteTable(); netstack_.SetInterfaces(interfaces);
type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI});
ip_observer_->RunAndExpectCallCount(1);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceAddedNoop) { TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceAddedNoop) {
netstack_.PushInterface( std::vector<fuchsia::netstack::NetInterface> interfaces(1);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, interfaces[0] = DefaultNetInterface();
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
CreateNotifier();
netstack_.PushInterface( netstack_.SetInterfaces(interfaces);
CreateNetInterface(kSecondaryNic, fuchsia::netstack::NetInterfaceFlagUp, CreateNotifier();
0, CreateIPv4Address(169, 254, 0, 2),
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.PushInterface(
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0,
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.NotifyInterfaces(); interfaces.push_back(SecondaryNetInterface());
netstack_.SetInterfaces(interfaces);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceDeletedNoop) { TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceDeletedNoop) {
netstack_.PushInterface( std::vector<fuchsia::netstack::NetInterface> interfaces(2);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, interfaces[0] = DefaultNetInterface();
CreateIPv4Address(169, 254, 0, 1), interfaces[1] = SecondaryNetInterface();
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.PushInterface(
CreateNetInterface(kSecondaryNic, fuchsia::netstack::NetInterfaceFlagUp,
0, CreateIPv4Address(169, 254, 0, 2),
CreateIPv4Address(255, 255, 255, 0), {}));
CreateNotifier();
netstack_.PushInterface( netstack_.SetInterfaces(interfaces);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, CreateNotifier();
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {}));
netstack_.NotifyInterfaces(); interfaces.pop_back();
netstack_.SetInterfaces(interfaces);
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, FoundWiFi) { TEST_F(NetworkChangeNotifierFuchsiaTest, FoundWiFi) {
netstack_.PushInterface( std::vector<fuchsia::netstack::NetInterface> interfaces(1);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, interfaces[0] = DefaultNetInterface();
fuchsia::hardware::ethernet::INFO_FEATURE_WLAN, interfaces[0].features = fuchsia::hardware::ethernet::INFO_FEATURE_WLAN;
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {})); netstack_.SetInterfaces(interfaces);
CreateNotifier(); CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, FindsInterfaceWithRequiredFeature) { TEST_F(NetworkChangeNotifierFuchsiaTest, FindsInterfaceWithRequiredFeature) {
netstack_.PushInterface( std::vector<fuchsia::netstack::NetInterface> interfaces(1);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, interfaces[0] = DefaultNetInterface();
fuchsia::hardware::ethernet::INFO_FEATURE_WLAN, interfaces[0].features = fuchsia::hardware::ethernet::INFO_FEATURE_WLAN;
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {})); netstack_.SetInterfaces(interfaces);
CreateNotifier(fuchsia::hardware::ethernet::INFO_FEATURE_WLAN); CreateNotifier(fuchsia::hardware::ethernet::INFO_FEATURE_WLAN);
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
} }
TEST_F(NetworkChangeNotifierFuchsiaTest, IgnoresInterfaceWithMissingFeature) { TEST_F(NetworkChangeNotifierFuchsiaTest, IgnoresInterfaceWithMissingFeature) {
netstack_.PushInterface( std::vector<fuchsia::netstack::NetInterface> interfaces(1);
CreateNetInterface(kDefaultNic, fuchsia::netstack::NetInterfaceFlagUp, 0, interfaces[0] = DefaultNetInterface();
CreateIPv4Address(169, 254, 0, 1),
CreateIPv4Address(255, 255, 255, 0), {})); netstack_.SetInterfaces(interfaces);
CreateNotifier(fuchsia::hardware::ethernet::INFO_FEATURE_WLAN); CreateNotifier(fuchsia::hardware::ethernet::INFO_FEATURE_WLAN);
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE, EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
notifier_->GetCurrentConnectionType()); notifier_->GetCurrentConnectionType());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment