• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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