Home | History | Annotate | Download | only in android
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // See network_change_notifier_android.h for design explanations.
      6 
      7 #include "base/basictypes.h"
      8 #include "base/bind.h"
      9 #include "base/callback.h"
     10 #include "base/compiler_specific.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "net/android/network_change_notifier_android.h"
     13 #include "net/android/network_change_notifier_delegate_android.h"
     14 #include "net/base/network_change_notifier.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace net {
     18 
     19 namespace {
     20 
     21 class NetworkChangeNotifierDelegateAndroidObserver
     22     : public NetworkChangeNotifierDelegateAndroid::Observer {
     23  public:
     24   NetworkChangeNotifierDelegateAndroidObserver() : notifications_count_(0) {}
     25 
     26   // NetworkChangeNotifierDelegateAndroid::Observer:
     27   virtual void OnConnectionTypeChanged() OVERRIDE {
     28     notifications_count_++;
     29   }
     30 
     31   int notifications_count() const {
     32     return notifications_count_;
     33   }
     34 
     35  private:
     36   int notifications_count_;
     37 };
     38 
     39 class NetworkChangeNotifierObserver
     40     : public NetworkChangeNotifier::ConnectionTypeObserver {
     41  public:
     42   NetworkChangeNotifierObserver() : notifications_count_(0) {}
     43 
     44   // NetworkChangeNotifier::Observer:
     45   virtual void OnConnectionTypeChanged(
     46       NetworkChangeNotifier::ConnectionType connection_type) OVERRIDE {
     47     notifications_count_++;
     48   }
     49 
     50   int notifications_count() const {
     51     return notifications_count_;
     52   }
     53 
     54  private:
     55   int notifications_count_;
     56 };
     57 
     58 }  // namespace
     59 
     60 class BaseNetworkChangeNotifierAndroidTest : public testing::Test {
     61  protected:
     62   typedef NetworkChangeNotifier::ConnectionType ConnectionType;
     63 
     64   virtual ~BaseNetworkChangeNotifierAndroidTest() {}
     65 
     66   void RunTest(
     67       const base::Callback<int(void)>& notifications_count_getter,
     68       const base::Callback<ConnectionType(void)>&  connection_type_getter) {
     69     EXPECT_EQ(0, notifications_count_getter.Run());
     70     EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
     71               connection_type_getter.Run());
     72 
     73     // Changing from online to offline should trigger a notification.
     74     SetOffline();
     75     EXPECT_EQ(1, notifications_count_getter.Run());
     76     EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
     77               connection_type_getter.Run());
     78 
     79     // No notification should be triggered when the offline state hasn't
     80     // changed.
     81     SetOffline();
     82     EXPECT_EQ(1, notifications_count_getter.Run());
     83     EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
     84               connection_type_getter.Run());
     85 
     86     // Going from offline to online should trigger a notification.
     87     SetOnline();
     88     EXPECT_EQ(2, notifications_count_getter.Run());
     89     EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
     90               connection_type_getter.Run());
     91   }
     92 
     93   void SetOnline() {
     94     delegate_.SetOnline();
     95     // Note that this is needed because ObserverListThreadSafe uses PostTask().
     96     base::MessageLoop::current()->RunUntilIdle();
     97   }
     98 
     99   void SetOffline() {
    100     delegate_.SetOffline();
    101     // See comment above.
    102     base::MessageLoop::current()->RunUntilIdle();
    103   }
    104 
    105   NetworkChangeNotifierDelegateAndroid delegate_;
    106 };
    107 
    108 // Tests that NetworkChangeNotifierDelegateAndroid is initialized with the
    109 // actual connection type rather than a hardcoded one (e.g.
    110 // CONNECTION_UNKNOWN). Initializing the connection type to CONNECTION_UNKNOWN
    111 // and relying on the first network change notification to set it correctly can
    112 // be problematic in case there is a long delay between the delegate's
    113 // construction and the notification.
    114 TEST_F(BaseNetworkChangeNotifierAndroidTest,
    115        DelegateIsInitializedWithCurrentConnectionType) {
    116   SetOffline();
    117   ASSERT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
    118             delegate_.GetCurrentConnectionType());
    119   // Instantiate another delegate to validate that it uses the actual
    120   // connection type at construction.
    121   scoped_ptr<NetworkChangeNotifierDelegateAndroid> other_delegate(
    122       new NetworkChangeNotifierDelegateAndroid());
    123   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
    124             other_delegate->GetCurrentConnectionType());
    125 
    126   // Toggle the global connectivity state and instantiate another delegate
    127   // again.
    128   SetOnline();
    129   ASSERT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
    130             delegate_.GetCurrentConnectionType());
    131   other_delegate.reset(new NetworkChangeNotifierDelegateAndroid());
    132   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
    133             other_delegate->GetCurrentConnectionType());
    134 }
    135 
    136 class NetworkChangeNotifierDelegateAndroidTest
    137     : public BaseNetworkChangeNotifierAndroidTest {
    138  protected:
    139   NetworkChangeNotifierDelegateAndroidTest() {
    140     delegate_.AddObserver(&delegate_observer_);
    141     delegate_.AddObserver(&other_delegate_observer_);
    142   }
    143 
    144   virtual ~NetworkChangeNotifierDelegateAndroidTest() {
    145     delegate_.RemoveObserver(&delegate_observer_);
    146     delegate_.RemoveObserver(&other_delegate_observer_);
    147   }
    148 
    149   NetworkChangeNotifierDelegateAndroidObserver delegate_observer_;
    150   NetworkChangeNotifierDelegateAndroidObserver other_delegate_observer_;
    151 };
    152 
    153 // Tests that the NetworkChangeNotifierDelegateAndroid's observers are notified.
    154 // A testing-only observer is used here for testing. In production the
    155 // delegate's observers are instances of NetworkChangeNotifierAndroid.
    156 TEST_F(NetworkChangeNotifierDelegateAndroidTest, DelegateObserverNotified) {
    157   // Test the logic with a single observer.
    158   RunTest(
    159       base::Bind(
    160           &NetworkChangeNotifierDelegateAndroidObserver::notifications_count,
    161           base::Unretained(&delegate_observer_)),
    162       base::Bind(
    163           &NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionType,
    164           base::Unretained(&delegate_)));
    165   // Check that *all* the observers are notified. Both observers should have the
    166   // same state.
    167   EXPECT_EQ(delegate_observer_.notifications_count(),
    168             other_delegate_observer_.notifications_count());
    169 }
    170 
    171 class NetworkChangeNotifierAndroidTest
    172     : public BaseNetworkChangeNotifierAndroidTest {
    173  protected:
    174   NetworkChangeNotifierAndroidTest() : notifier_(&delegate_) {
    175     NetworkChangeNotifier::AddConnectionTypeObserver(
    176         &connection_type_observer_);
    177     NetworkChangeNotifier::AddConnectionTypeObserver(
    178         &other_connection_type_observer_);
    179   }
    180 
    181   NetworkChangeNotifierObserver connection_type_observer_;
    182   NetworkChangeNotifierObserver other_connection_type_observer_;
    183   NetworkChangeNotifier::DisableForTest disable_for_test_;
    184   NetworkChangeNotifierAndroid notifier_;
    185 };
    186 
    187 // When a NetworkChangeNotifierAndroid is observing a
    188 // NetworkChangeNotifierDelegateAndroid for network state changes, and the
    189 // NetworkChangeNotifierDelegateAndroid's connectivity state changes, the
    190 // NetworkChangeNotifierAndroid should reflect that state.
    191 TEST_F(NetworkChangeNotifierAndroidTest,
    192        NotificationsSentToNetworkChangeNotifierAndroid) {
    193   RunTest(
    194       base::Bind(
    195           &NetworkChangeNotifierObserver::notifications_count,
    196           base::Unretained(&connection_type_observer_)),
    197       base::Bind(
    198           &NetworkChangeNotifierAndroid::GetCurrentConnectionType,
    199           base::Unretained(&notifier_)));
    200 }
    201 
    202 // When a NetworkChangeNotifierAndroid's connection state changes, it should
    203 // notify all of its observers.
    204 TEST_F(NetworkChangeNotifierAndroidTest,
    205        NotificationsSentToClientsOfNetworkChangeNotifier) {
    206   RunTest(
    207       base::Bind(
    208           &NetworkChangeNotifierObserver::notifications_count,
    209           base::Unretained(&connection_type_observer_)),
    210       base::Bind(&NetworkChangeNotifier::GetConnectionType));
    211   // Check that *all* the observers are notified.
    212   EXPECT_EQ(connection_type_observer_.notifications_count(),
    213             other_connection_type_observer_.notifications_count());
    214 }
    215 
    216 }  // namespace net
    217