#include "net/android/network_change_notifier_android.h"
#include <memory>
#include "base/compiler_specific.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/run_loop.h"
#include "net/android/network_change_notifier_delegate_android.h"
#include "net/base/ip_address.h"
#include "net/base/network_change_notifier.h"
#include "net/test/test_with_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
enum ChangeType {
NONE,
CONNECTED,
SOON_TO_DISCONNECT,
DISCONNECTED,
MADE_DEFAULT,
};
class NetworkChangeNotifierDelegateAndroidObserver
: public NetworkChangeNotifierDelegateAndroid::Observer {
public:
typedef NetworkChangeNotifier::ConnectionCost ConnectionCost;
typedef NetworkChangeNotifier::ConnectionType ConnectionType;
typedef NetworkChangeNotifier::NetworkList NetworkList;
NetworkChangeNotifierDelegateAndroidObserver() = default;
void OnConnectionTypeChanged() override { type_notifications_count_++; }
void OnConnectionCostChanged() override { cost_notifications_count_++; }
void OnMaxBandwidthChanged(
double max_bandwidth_mbps,
net::NetworkChangeNotifier::ConnectionType type) override {
max_bandwidth_notifications_count_++;
}
void OnNetworkConnected(handles::NetworkHandle network) override {}
void OnNetworkSoonToDisconnect(handles::NetworkHandle network) override {}
void OnNetworkDisconnected(handles::NetworkHandle network) override {}
void OnNetworkMadeDefault(handles::NetworkHandle network) override {}
void OnDefaultNetworkActive() override {
default_network_active_notifications_count_++;
}
int type_notifications_count() const { return type_notifications_count_; }
int cost_notifications_count() const { return cost_notifications_count_; }
int bandwidth_notifications_count() const {
return max_bandwidth_notifications_count_;
}
int default_network_active_notifications_count() const {
return default_network_active_notifications_count_;
}
private:
int type_notifications_count_ = 0;
int cost_notifications_count_ = 0;
int max_bandwidth_notifications_count_ = 0;
int default_network_active_notifications_count_ = 0;
};
class NetworkChangeNotifierObserver
: public NetworkChangeNotifier::ConnectionTypeObserver {
public:
NetworkChangeNotifierObserver() = default;
void OnConnectionTypeChanged(
NetworkChangeNotifier::ConnectionType connection_type) override {
notifications_count_++;
}
int notifications_count() const {
return notifications_count_;
}
private:
int notifications_count_ = 0;
};
class NetworkChangeNotifierConnectionCostObserver
: public NetworkChangeNotifier::ConnectionCostObserver {
public:
void OnConnectionCostChanged(
NetworkChangeNotifier::ConnectionCost cost) override {
notifications_count_++;
}
int notifications_count() const { return notifications_count_; }
private:
int notifications_count_ = 0;
};
class NetworkChangeNotifierMaxBandwidthObserver
: public NetworkChangeNotifier::MaxBandwidthObserver {
public:
void OnMaxBandwidthChanged(
double max_bandwidth_mbps,
NetworkChangeNotifier::ConnectionType type) override {
notifications_count_++;
}
int notifications_count() const { return notifications_count_; }
private:
int notifications_count_ = 0;
};
class TestNetworkObserver : public NetworkChangeNotifier::NetworkObserver {
public:
TestNetworkObserver() { Clear(); }
void ExpectChange(ChangeType change, handles::NetworkHandle network) {
EXPECT_EQ(last_change_type_, change);
EXPECT_EQ(last_network_changed_, network);
Clear();
}
private:
void Clear() {
last_change_type_ = NONE;
last_network_changed_ = handles::kInvalidNetworkHandle;
}
void OnNetworkConnected(handles::NetworkHandle network) override {
ExpectChange(NONE, handles::kInvalidNetworkHandle);
last_change_type_ = CONNECTED;
last_network_changed_ = network;
}
void OnNetworkSoonToDisconnect(handles::NetworkHandle network) override {
ExpectChange(NONE, handles::kInvalidNetworkHandle);
last_change_type_ = SOON_TO_DISCONNECT;
last_network_changed_ = network;
}
void OnNetworkDisconnected(handles::NetworkHandle network) override {
ExpectChange(NONE, handles::kInvalidNetworkHandle);
last_change_type_ = DISCONNECTED;
last_network_changed_ = network;
}
void OnNetworkMadeDefault(handles::NetworkHandle network) override {
last_change_type_ = MADE_DEFAULT;
last_network_changed_ = network;
}
ChangeType last_change_type_;
handles::NetworkHandle last_network_changed_;
};
}
class BaseNetworkChangeNotifierAndroidTest : public TestWithTaskEnvironment {
protected:
typedef NetworkChangeNotifier::ConnectionType ConnectionType;
typedef NetworkChangeNotifier::ConnectionCost ConnectionCost;
typedef NetworkChangeNotifier::ConnectionSubtype ConnectionSubtype;
~BaseNetworkChangeNotifierAndroidTest() override = default;
void RunTest(
const base::RepeatingCallback<int(void)>& notifications_count_getter,
const base::RepeatingCallback<ConnectionType(void)>&
connection_type_getter) {
EXPECT_EQ(0, notifications_count_getter.Run());
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
connection_type_getter.Run());
SetOffline();
EXPECT_EQ(1, notifications_count_getter.Run());
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
connection_type_getter.Run());
SetOffline();
EXPECT_EQ(1, notifications_count_getter.Run());
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
connection_type_getter.Run());
SetOnline();
EXPECT_EQ(2, notifications_count_getter.Run());
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
connection_type_getter.Run());
}
void SetOnline(bool drain_run_loop = true) {
delegate_.SetOnline();
if (drain_run_loop) {
base::RunLoop().RunUntilIdle();
}
}
void SetOffline(bool drain_run_loop = true) {
delegate_.SetOffline();
if (drain_run_loop) {
base::RunLoop().RunUntilIdle();
}
}
void FakeConnectionCostChange(ConnectionCost cost) {
delegate_.FakeConnectionCostChanged(cost);
base::RunLoop().RunUntilIdle();
}
void FakeConnectionSubtypeChange(ConnectionSubtype subtype) {
delegate_.FakeConnectionSubtypeChanged(subtype);
base::RunLoop().RunUntilIdle();
}
void FakeNetworkChange(ChangeType change,
handles::NetworkHandle network,
ConnectionType type) {
switch (change) {
case CONNECTED:
delegate_.FakeNetworkConnected(network, type);
break;
case SOON_TO_DISCONNECT:
delegate_.FakeNetworkSoonToBeDisconnected(network);
break;
case DISCONNECTED:
delegate_.FakeNetworkDisconnected(network);
break;
case MADE_DEFAULT:
delegate_.FakeDefaultNetwork(network, type);
break;
case NONE:
NOTREACHED();
}
base::RunLoop().RunUntilIdle();
}
void FakeDefaultNetworkActive() {
delegate_.FakeDefaultNetworkActive();
base::RunLoop().RunUntilIdle();
}
void FakePurgeActiveNetworkList(NetworkChangeNotifier::NetworkList networks) {
delegate_.FakePurgeActiveNetworkList(networks);
base::RunLoop().RunUntilIdle();
}
NetworkChangeNotifierDelegateAndroid delegate_;
};
TEST_F(BaseNetworkChangeNotifierAndroidTest,
DelegateIsInitializedWithCurrentConnectionType) {
SetOffline();
ASSERT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
delegate_.GetCurrentConnectionType());
auto other_delegate =
std::make_unique<NetworkChangeNotifierDelegateAndroid>();
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
other_delegate->GetCurrentConnectionType());
SetOnline();
ASSERT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
delegate_.GetCurrentConnectionType());
other_delegate = std::make_unique<NetworkChangeNotifierDelegateAndroid>();
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
other_delegate->GetCurrentConnectionType());
}
class NetworkChangeNotifierAndroidTest
: public BaseNetworkChangeNotifierAndroidTest {
protected:
NetworkChangeNotifierAndroidTest() : notifier_(&delegate_) {
NetworkChangeNotifier::AddConnectionTypeObserver(
&connection_type_observer_);
NetworkChangeNotifier::AddConnectionTypeObserver(
&other_connection_type_observer_);
NetworkChangeNotifier::AddConnectionCostObserver(
&connection_cost_observer_);
NetworkChangeNotifier::AddMaxBandwidthObserver(&max_bandwidth_observer_);
}
void ForceNetworkHandlesSupportedForTesting() {
notifier_.ForceNetworkHandlesSupportedForTesting();
}
NetworkChangeNotifierObserver connection_type_observer_;
NetworkChangeNotifierConnectionCostObserver connection_cost_observer_;
NetworkChangeNotifierMaxBandwidthObserver max_bandwidth_observer_;
NetworkChangeNotifierObserver other_connection_type_observer_;
NetworkChangeNotifier::DisableForTest disable_for_test_;
NetworkChangeNotifierAndroid notifier_;
};
class NetworkChangeNotifierDelegateAndroidTest
: public BaseNetworkChangeNotifierAndroidTest {
protected:
NetworkChangeNotifierDelegateAndroidTest() {
delegate_.RegisterObserver(&delegate_observer_);
}
~NetworkChangeNotifierDelegateAndroidTest() override {
delegate_.UnregisterObserver(&delegate_observer_);
}
NetworkChangeNotifierDelegateAndroidObserver delegate_observer_;
};
TEST_F(NetworkChangeNotifierDelegateAndroidTest, DelegateObserverNotified) {
RunTest(base::BindRepeating(&NetworkChangeNotifierDelegateAndroidObserver::
type_notifications_count,
base::Unretained(&delegate_observer_)),
base::BindRepeating(
&NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionType,
base::Unretained(&delegate_)));
}
TEST_F(NetworkChangeNotifierAndroidTest,
NotificationsSentToNetworkChangeNotifierAndroid) {
RunTest(
base::BindRepeating(&NetworkChangeNotifierObserver::notifications_count,
base::Unretained(&connection_type_observer_)),
base::BindRepeating(
&NetworkChangeNotifierAndroid::GetCurrentConnectionType,
base::Unretained(¬ifier_)));
}
TEST_F(NetworkChangeNotifierAndroidTest,
NotificationsSentToClientsOfNetworkChangeNotifier) {
RunTest(
base::BindRepeating(&NetworkChangeNotifierObserver::notifications_count,
base::Unretained(&connection_type_observer_)),
base::BindRepeating(&NetworkChangeNotifier::GetConnectionType));
EXPECT_EQ(connection_type_observer_.notifications_count(),
other_connection_type_observer_.notifications_count());
}
TEST_F(NetworkChangeNotifierAndroidTest, ConnectionCost) {
FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_UNMETERED);
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_COST_UNMETERED,
notifier_.GetConnectionCost());
FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_METERED);
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_COST_METERED,
notifier_.GetConnectionCost());
}
TEST_F(NetworkChangeNotifierAndroidTest, ConnectionCostCallbackNotifier) {
FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_UNMETERED);
EXPECT_EQ(1, connection_cost_observer_.notifications_count());
FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_METERED);
EXPECT_EQ(2, connection_cost_observer_.notifications_count());
}
TEST_F(NetworkChangeNotifierDelegateAndroidTest,
ConnectionCostCallbackNotifier) {
EXPECT_EQ(0, delegate_observer_.cost_notifications_count());
FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_UNMETERED);
EXPECT_EQ(1, delegate_observer_.cost_notifications_count());
FakeConnectionCostChange(ConnectionCost::CONNECTION_COST_METERED);
EXPECT_EQ(2, delegate_observer_.cost_notifications_count());
}
TEST_F(NetworkChangeNotifierAndroidTest, MaxBandwidth) {
SetOnline();
double max_bandwidth_mbps = 0.0;
NetworkChangeNotifier::ConnectionType connection_type =
NetworkChangeNotifier::CONNECTION_NONE;
notifier_.GetMaxBandwidthAndConnectionType(&max_bandwidth_mbps,
&connection_type);
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN, connection_type);
EXPECT_EQ(std::numeric_limits<double>::infinity(), max_bandwidth_mbps);
SetOffline();
notifier_.GetMaxBandwidthAndConnectionType(&max_bandwidth_mbps,
&connection_type);
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE, connection_type);
EXPECT_EQ(0.0, max_bandwidth_mbps);
}
TEST_F(NetworkChangeNotifierAndroidTest, MaxBandwidthCallbackNotifier) {
FakeConnectionSubtypeChange(ConnectionSubtype::SUBTYPE_CDMA);
EXPECT_EQ(1, max_bandwidth_observer_.notifications_count());
FakeConnectionSubtypeChange(ConnectionSubtype::SUBTYPE_CDMA);
EXPECT_EQ(2, max_bandwidth_observer_.notifications_count());
FakeConnectionSubtypeChange(ConnectionSubtype::SUBTYPE_LTE);
EXPECT_EQ(3, max_bandwidth_observer_.notifications_count());
}
TEST_F(NetworkChangeNotifierDelegateAndroidTest,
MaxBandwidthNotifiedOnConnectionChange) {
EXPECT_EQ(0, delegate_observer_.bandwidth_notifications_count());
SetOffline();
EXPECT_EQ(1, delegate_observer_.bandwidth_notifications_count());
SetOnline();
EXPECT_EQ(2, delegate_observer_.bandwidth_notifications_count());
SetOnline();
EXPECT_EQ(2, delegate_observer_.bandwidth_notifications_count());
}
TEST_F(NetworkChangeNotifierAndroidTest, NetworkCallbacks) {
ForceNetworkHandlesSupportedForTesting();
TestNetworkObserver network_observer;
NetworkChangeNotifier::AddNetworkObserver(&network_observer);
EXPECT_EQ(handles::kInvalidNetworkHandle,
NetworkChangeNotifier::GetDefaultNetwork());
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
NetworkChangeNotifier::GetNetworkConnectionType(100));
NetworkChangeNotifier::NetworkList network_list;
NetworkChangeNotifier::GetConnectedNetworks(&network_list);
EXPECT_EQ(0u, network_list.size());
FakeNetworkChange(CONNECTED, 100, NetworkChangeNotifier::CONNECTION_WIFI);
network_observer.ExpectChange(CONNECTED, 100);
EXPECT_EQ(handles::kInvalidNetworkHandle,
NetworkChangeNotifier::GetDefaultNetwork());
NetworkChangeNotifier::GetConnectedNetworks(&network_list);
EXPECT_EQ(1u, network_list.size());
EXPECT_EQ(100, network_list[0]);
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_WIFI,
NetworkChangeNotifier::GetNetworkConnectionType(100));
FakeNetworkChange(CONNECTED, 100, NetworkChangeNotifier::CONNECTION_WIFI);
network_observer.ExpectChange(NONE, handles::kInvalidNetworkHandle);
FakeNetworkChange(CONNECTED, 101, NetworkChangeNotifier::CONNECTION_3G);
network_observer.ExpectChange(CONNECTED, 101);
NetworkChangeNotifier::GetConnectedNetworks(&network_list);
EXPECT_EQ(2u, network_list.size());
EXPECT_EQ(100, network_list[0]);
EXPECT_EQ(101, network_list[1]);
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_WIFI,
NetworkChangeNotifier::GetNetworkConnectionType(100));
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_3G,
NetworkChangeNotifier::GetNetworkConnectionType(101));
FakeNetworkChange(SOON_TO_DISCONNECT, 100,
NetworkChangeNotifier::CONNECTION_WIFI);
network_observer.ExpectChange(SOON_TO_DISCONNECT, 100);
NetworkChangeNotifier::GetConnectedNetworks(&network_list);
EXPECT_EQ(2u, network_list.size());
EXPECT_EQ(100, network_list[0]);
EXPECT_EQ(101, network_list[1]);
FakeNetworkChange(DISCONNECTED, 100, NetworkChangeNotifier::CONNECTION_WIFI);
network_observer.ExpectChange(DISCONNECTED, 100);
NetworkChangeNotifier::GetConnectedNetworks(&network_list);
EXPECT_EQ(1u, network_list.size());
EXPECT_EQ(101, network_list[0]);
FakeNetworkChange(DISCONNECTED, 100, NetworkChangeNotifier::CONNECTION_WIFI);
network_observer.ExpectChange(NONE, handles::kInvalidNetworkHandle);
FakeNetworkChange(MADE_DEFAULT, 100, NetworkChangeNotifier::CONNECTION_WIFI);
network_observer.ExpectChange(NONE, handles::kInvalidNetworkHandle);
FakeNetworkChange(CONNECTED, 100, NetworkChangeNotifier::CONNECTION_WIFI);
network_observer.ExpectChange(MADE_DEFAULT, 100);
EXPECT_EQ(100, NetworkChangeNotifier::GetDefaultNetwork());
FakeNetworkChange(MADE_DEFAULT, 101, NetworkChangeNotifier::CONNECTION_3G);
network_observer.ExpectChange(MADE_DEFAULT, 101);
EXPECT_EQ(101, NetworkChangeNotifier::GetDefaultNetwork());
FakeNetworkChange(MADE_DEFAULT, 101, NetworkChangeNotifier::CONNECTION_3G);
network_observer.ExpectChange(NONE, handles::kInvalidNetworkHandle);
FakeNetworkChange(CONNECTED, 101, NetworkChangeNotifier::CONNECTION_4G);
network_observer.ExpectChange(NONE, handles::kInvalidNetworkHandle);
EXPECT_EQ(NetworkChangeNotifier::CONNECTION_4G,
NetworkChangeNotifier::GetNetworkConnectionType(101));
NetworkChangeNotifier::GetConnectedNetworks(&network_list);
EXPECT_EQ(2u, network_list.size());
EXPECT_EQ(100, network_list[0]);
EXPECT_EQ(101, network_list[1]);
network_list.erase(network_list.begin() + 1);
FakePurgeActiveNetworkList(network_list);
network_observer.ExpectChange(DISCONNECTED, 101);
NetworkChangeNotifier::GetConnectedNetworks(&network_list);
EXPECT_EQ(1u, network_list.size());
EXPECT_EQ(100, network_list[0]);
EXPECT_EQ(handles::kInvalidNetworkHandle,
NetworkChangeNotifier::GetDefaultNetwork());
NetworkChangeNotifier::RemoveNetworkObserver(&network_observer);
}
TEST_F(NetworkChangeNotifierDelegateAndroidTest, TypeChangeIsSynchronous) {
const int initial_value = delegate_observer_.type_notifications_count();
SetOffline(false);
EXPECT_EQ(initial_value + 1, delegate_observer_.type_notifications_count());
}
TEST_F(NetworkChangeNotifierDelegateAndroidTest, DefaultNetworkActive) {
EXPECT_EQ(0, delegate_observer_.default_network_active_notifications_count());
FakeDefaultNetworkActive();
EXPECT_EQ(0, delegate_observer_.default_network_active_notifications_count());
delegate_.DefaultNetworkActiveObserverAdded();
FakeDefaultNetworkActive();
EXPECT_EQ(1, delegate_observer_.default_network_active_notifications_count());
delegate_.DefaultNetworkActiveObserverAdded();
FakeDefaultNetworkActive();
EXPECT_EQ(2, delegate_observer_.default_network_active_notifications_count());
delegate_.DefaultNetworkActiveObserverRemoved();
FakeDefaultNetworkActive();
EXPECT_EQ(3, delegate_observer_.default_network_active_notifications_count());
delegate_.DefaultNetworkActiveObserverRemoved();
FakeDefaultNetworkActive();
EXPECT_EQ(3, delegate_observer_.default_network_active_notifications_count());
delegate_.DefaultNetworkActiveObserverAdded();
FakeDefaultNetworkActive();
EXPECT_EQ(4, delegate_observer_.default_network_active_notifications_count());
delegate_.DefaultNetworkActiveObserverRemoved();
}
}