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/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 12 using ::testing::AtLeast; 13 using ::testing::Invoke; 14 using ::testing::Return; 15 using ::testing::StrictMock; 16 17 namespace net { 18 19 namespace { 20 21 // Subclass of NetworkChangeNotifierWin that overrides functions so that no 22 // Windows API networking functions are ever called. 23 class 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 46 class 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 63 bool ExitMessageLoopAndReturnFalse() { 64 base::MessageLoop::current()->Quit(); 65 return false; 66 } 67 68 } // namespace 69 70 class 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 base::MessageLoop::current()->RunUntilIdle(); 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 base::MessageLoop::current()->RunUntilIdle(); 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 base::MessageLoop::current()->RunUntilIdle(); 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 base::MessageLoop::current()->RunUntilIdle(); 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()).Times(1) 169 .WillOnce( 170 Invoke(base::MessageLoop::current(), &base::MessageLoop::Quit)); 171 EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal()) 172 .Times(1).WillOnce(Return(true)); 173 174 base::MessageLoop::current()->Run(); 175 176 EXPECT_TRUE(network_change_notifier_.is_watching()); 177 EXPECT_EQ(0, network_change_notifier_.sequential_failures()); 178 } 179 180 // Runs the message loop until WatchForAddressChange is called again, as a 181 // result of the already posted task after a WatchForAddressChangeInternal 182 // failure. Simulates a failure on the resulting call to 183 // WatchForAddressChangeInternal. 184 void RetryAndFail() { 185 EXPECT_FALSE(network_change_notifier_.is_watching()); 186 EXPECT_LT(0, network_change_notifier_.sequential_failures()); 187 188 int initial_sequential_failures = 189 network_change_notifier_.sequential_failures(); 190 191 EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(0); 192 EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal()) 193 // Due to an expected race, it's theoretically possible for more than 194 // one call to occur, though unlikely. 195 .Times(AtLeast(1)) 196 .WillRepeatedly(Invoke(ExitMessageLoopAndReturnFalse)); 197 198 base::MessageLoop::current()->Run(); 199 200 EXPECT_FALSE(network_change_notifier_.is_watching()); 201 EXPECT_LT(initial_sequential_failures, 202 network_change_notifier_.sequential_failures()); 203 204 // If a task to notify observers of the IP address change event was 205 // incorrectly posted, make sure it gets run. 206 base::MessageLoop::current()->RunUntilIdle(); 207 } 208 209 private: 210 // Note that the order of declaration here is important. 211 212 // Allows creating a new NetworkChangeNotifier. Must be created before 213 // |network_change_notifier_| and destroyed after it to avoid DCHECK failures. 214 NetworkChangeNotifier::DisableForTest disable_for_test_; 215 216 StrictMock<TestNetworkChangeNotifierWin> network_change_notifier_; 217 218 // Must be created after |network_change_notifier_|, so it can add itself as 219 // an IPAddressObserver. 220 StrictMock<TestIPAddressObserver> test_ip_address_observer_; 221 }; 222 223 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinBasic) { 224 StartWatchingAndSucceed(); 225 } 226 227 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStart) { 228 StartWatchingAndFail(); 229 } 230 231 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartOnce) { 232 StartWatchingAndFail(); 233 RetryAndSucceed(); 234 } 235 236 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartTwice) { 237 StartWatchingAndFail(); 238 RetryAndFail(); 239 RetryAndSucceed(); 240 } 241 242 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinSignal) { 243 StartWatchingAndSucceed(); 244 SignalAndSucceed(); 245 } 246 247 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalOnce) { 248 StartWatchingAndSucceed(); 249 SignalAndFail(); 250 RetryAndSucceed(); 251 } 252 253 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalTwice) { 254 StartWatchingAndSucceed(); 255 SignalAndFail(); 256 RetryAndFail(); 257 RetryAndSucceed(); 258 } 259 260 } // namespace net 261