network_change_notifier_win_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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#include "base/message_loop.h" 6#include "net/base/network_change_notifier.h" 7#include "net/base/network_change_notifier_factory.h" 8#include "net/base/network_change_notifier_win.h" 9#include "testing/gmock/include/gmock/gmock.h" 10#include "testing/gtest/include/gtest/gtest.h" 11 12using ::testing::AtLeast; 13using ::testing::Invoke; 14using ::testing::Return; 15using ::testing::StrictMock; 16 17namespace net { 18 19namespace { 20 21// Subclass of NetworkChangeNotifierWin that overrides functions so that no 22// Windows API networking functions are ever called. 23class TestNetworkChangeNotifierWin : public NetworkChangeNotifierWin { 24 public: 25 TestNetworkChangeNotifierWin() {} 26 27 virtual ~TestNetworkChangeNotifierWin() { 28 // This is needed so we don't try to stop watching for IP address changes, 29 // as we never actually started. 30 set_is_watching(false); 31 } 32 33 // From NetworkChangeNotifier. 34 virtual NetworkChangeNotifier::ConnectionType 35 GetCurrentConnectionType() const OVERRIDE { 36 return NetworkChangeNotifier::CONNECTION_UNKNOWN; 37 } 38 39 // From NetworkChangeNotifierWin. 40 MOCK_METHOD0(WatchForAddressChangeInternal, bool()); 41 42 private: 43 DISALLOW_COPY_AND_ASSIGN(TestNetworkChangeNotifierWin); 44}; 45 46class TestIPAddressObserver 47 : public net::NetworkChangeNotifier::IPAddressObserver { 48 public: 49 TestIPAddressObserver() { 50 NetworkChangeNotifier::AddIPAddressObserver(this); 51 } 52 53 ~TestIPAddressObserver() { 54 NetworkChangeNotifier::RemoveIPAddressObserver(this); 55 } 56 57 MOCK_METHOD0(OnIPAddressChanged, void()); 58 59 private: 60 DISALLOW_COPY_AND_ASSIGN(TestIPAddressObserver); 61}; 62 63bool ExitMessageLoopAndReturnFalse() { 64 MessageLoop::current()->Quit(); 65 return false; 66} 67 68} // namespace 69 70class NetworkChangeNotifierWinTest : public testing::Test { 71 public: 72 // Calls WatchForAddressChange, and simulates a WatchForAddressChangeInternal 73 // success. Expects that |network_change_notifier_| has just been created, so 74 // it's not watching anything yet, and there have been no previous 75 // WatchForAddressChangeInternal failures. 76 void StartWatchingAndSucceed() { 77 EXPECT_FALSE(network_change_notifier_.is_watching()); 78 EXPECT_EQ(0, network_change_notifier_.sequential_failures()); 79 80 EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(0); 81 EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal()) 82 .Times(1) 83 .WillOnce(Return(true)); 84 85 network_change_notifier_.WatchForAddressChange(); 86 87 EXPECT_TRUE(network_change_notifier_.is_watching()); 88 EXPECT_EQ(0, network_change_notifier_.sequential_failures()); 89 90 // If a task to notify observers of the IP address change event was 91 // incorrectly posted, make sure it gets run to trigger a failure. 92 MessageLoop::current()->RunAllPending(); 93 } 94 95 // Calls WatchForAddressChange, and simulates a WatchForAddressChangeInternal 96 // failure. 97 void StartWatchingAndFail() { 98 EXPECT_FALSE(network_change_notifier_.is_watching()); 99 EXPECT_EQ(0, network_change_notifier_.sequential_failures()); 100 101 EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(0); 102 EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal()) 103 // Due to an expected race, it's theoretically possible for more than 104 // one call to occur, though unlikely. 105 .Times(AtLeast(1)) 106 .WillRepeatedly(Return(false)); 107 108 network_change_notifier_.WatchForAddressChange(); 109 110 EXPECT_FALSE(network_change_notifier_.is_watching()); 111 EXPECT_LT(0, network_change_notifier_.sequential_failures()); 112 113 // If a task to notify observers of the IP address change event was 114 // incorrectly posted, make sure it gets run. 115 MessageLoop::current()->RunAllPending(); 116 } 117 118 // Simulates a network change event, resulting in a call to OnObjectSignaled. 119 // The resulting call to WatchForAddressChangeInternal then succeeds. 120 void SignalAndSucceed() { 121 EXPECT_TRUE(network_change_notifier_.is_watching()); 122 EXPECT_EQ(0, network_change_notifier_.sequential_failures()); 123 124 EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(1); 125 EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal()) 126 .Times(1) 127 .WillOnce(Return(true)); 128 129 network_change_notifier_.OnObjectSignaled(INVALID_HANDLE_VALUE); 130 131 EXPECT_TRUE(network_change_notifier_.is_watching()); 132 EXPECT_EQ(0, network_change_notifier_.sequential_failures()); 133 134 // Run the task to notify observers of the IP address change event. 135 MessageLoop::current()->RunAllPending(); 136 } 137 138 // Simulates a network change event, resulting in a call to OnObjectSignaled. 139 // The resulting call to WatchForAddressChangeInternal then fails. 140 void SignalAndFail() { 141 EXPECT_TRUE(network_change_notifier_.is_watching()); 142 EXPECT_EQ(0, network_change_notifier_.sequential_failures()); 143 144 EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(1); 145 EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal()) 146 // Due to an expected race, it's theoretically possible for more than 147 // one call to occur, though unlikely. 148 .Times(AtLeast(1)) 149 .WillRepeatedly(Return(false)); 150 151 network_change_notifier_.OnObjectSignaled(INVALID_HANDLE_VALUE); 152 153 EXPECT_FALSE(network_change_notifier_.is_watching()); 154 EXPECT_LT(0, network_change_notifier_.sequential_failures()); 155 156 // Run the task to notify observers of the IP address change event. 157 MessageLoop::current()->RunAllPending(); 158 } 159 160 // Runs the message loop until WatchForAddressChange is called again, as a 161 // result of the already posted task after a WatchForAddressChangeInternal 162 // failure. Simulates a success on the resulting call to 163 // WatchForAddressChangeInternal. 164 void RetryAndSucceed() { 165 EXPECT_FALSE(network_change_notifier_.is_watching()); 166 EXPECT_LT(0, network_change_notifier_.sequential_failures()); 167 168 EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()) 169 .Times(1) 170 .WillOnce(Invoke(MessageLoop::current(), &MessageLoop::Quit)); 171 EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal()) 172 .Times(1) 173 .WillOnce(Return(true)); 174 175 MessageLoop::current()->Run(); 176 177 EXPECT_TRUE(network_change_notifier_.is_watching()); 178 EXPECT_EQ(0, network_change_notifier_.sequential_failures()); 179 } 180 181 // Runs the message loop until WatchForAddressChange is called again, as a 182 // result of the already posted task after a WatchForAddressChangeInternal 183 // failure. Simulates a failure on the resulting call to 184 // WatchForAddressChangeInternal. 185 void RetryAndFail() { 186 EXPECT_FALSE(network_change_notifier_.is_watching()); 187 EXPECT_LT(0, network_change_notifier_.sequential_failures()); 188 189 int initial_sequential_failures = 190 network_change_notifier_.sequential_failures(); 191 192 EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(0); 193 EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal()) 194 // Due to an expected race, it's theoretically possible for more than 195 // one call to occur, though unlikely. 196 .Times(AtLeast(1)) 197 .WillRepeatedly(Invoke(ExitMessageLoopAndReturnFalse)); 198 199 MessageLoop::current()->Run(); 200 201 EXPECT_FALSE(network_change_notifier_.is_watching()); 202 EXPECT_LT(initial_sequential_failures, 203 network_change_notifier_.sequential_failures()); 204 205 // If a task to notify observers of the IP address change event was 206 // incorrectly posted, make sure it gets run. 207 MessageLoop::current()->RunAllPending(); 208 } 209 210 private: 211 // Note that the order of declaration here is important. 212 213 // Allows creating a new NetworkChangeNotifier. Must be created before 214 // |network_change_notifier_| and destroyed after it to avoid DCHECK failures. 215 NetworkChangeNotifier::DisableForTest disable_for_test_; 216 217 StrictMock<TestNetworkChangeNotifierWin> network_change_notifier_; 218 219 // Must be created after |network_change_notifier_|, so it can add itself as 220 // an IPAddressObserver. 221 StrictMock<TestIPAddressObserver> test_ip_address_observer_; 222}; 223 224TEST_F(NetworkChangeNotifierWinTest, NetChangeWinBasic) { 225 StartWatchingAndSucceed(); 226} 227 228TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStart) { 229 StartWatchingAndFail(); 230} 231 232TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartOnce) { 233 StartWatchingAndFail(); 234 RetryAndSucceed(); 235} 236 237TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartTwice) { 238 StartWatchingAndFail(); 239 RetryAndFail(); 240 RetryAndSucceed(); 241} 242 243TEST_F(NetworkChangeNotifierWinTest, NetChangeWinSignal) { 244 StartWatchingAndSucceed(); 245 SignalAndSucceed(); 246} 247 248TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalOnce) { 249 StartWatchingAndSucceed(); 250 SignalAndFail(); 251 RetryAndSucceed(); 252} 253 254TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalTwice) { 255 StartWatchingAndSucceed(); 256 SignalAndFail(); 257 RetryAndFail(); 258 RetryAndSucceed(); 259} 260 261} // namespace net 262