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:
TestNetworkChangeNotifierWin()25 TestNetworkChangeNotifierWin() {}
26
~TestNetworkChangeNotifierWin()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 NetworkChangeNotifierWin.
34 virtual NetworkChangeNotifier::ConnectionType
RecomputeCurrentConnectionType() const35 RecomputeCurrentConnectionType() 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:
TestIPAddressObserver()49 TestIPAddressObserver() {
50 NetworkChangeNotifier::AddIPAddressObserver(this);
51 }
52
~TestIPAddressObserver()53 ~TestIPAddressObserver() {
54 NetworkChangeNotifier::RemoveIPAddressObserver(this);
55 }
56
57 MOCK_METHOD0(OnIPAddressChanged, void());
58
59 private:
60 DISALLOW_COPY_AND_ASSIGN(TestIPAddressObserver);
61 };
62
ExitMessageLoopAndReturnFalse()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.
StartWatchingAndSucceed()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.
StartWatchingAndFail()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.
SignalAndSucceed()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.
SignalAndFail()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.
RetryAndSucceed()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.
RetryAndFail()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
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinBasic)223 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinBasic) {
224 StartWatchingAndSucceed();
225 }
226
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailStart)227 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStart) {
228 StartWatchingAndFail();
229 }
230
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailStartOnce)231 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartOnce) {
232 StartWatchingAndFail();
233 RetryAndSucceed();
234 }
235
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailStartTwice)236 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartTwice) {
237 StartWatchingAndFail();
238 RetryAndFail();
239 RetryAndSucceed();
240 }
241
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinSignal)242 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinSignal) {
243 StartWatchingAndSucceed();
244 SignalAndSucceed();
245 }
246
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailSignalOnce)247 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalOnce) {
248 StartWatchingAndSucceed();
249 SignalAndFail();
250 RetryAndSucceed();
251 }
252
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailSignalTwice)253 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalTwice) {
254 StartWatchingAndSucceed();
255 SignalAndFail();
256 RetryAndFail();
257 RetryAndSucceed();
258 }
259
260 } // namespace net
261