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 17namespace net { 18 19namespace { 20 21class 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 39class 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 60class 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. 114TEST_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 136class 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. 156TEST_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 171class 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. 191TEST_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(¬ifier_))); 200} 201 202// When a NetworkChangeNotifierAndroid's connection state changes, it should 203// notify all of its observers. 204TEST_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