xref: /aosp_15_r20/external/cronet/net/base/network_change_notifier_win_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
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 "net/base/network_change_notifier_win.h"
6 
7 #include <utility>
8 
9 #include "base/functional/bind.h"
10 #include "base/run_loop.h"
11 #include "base/task/sequenced_task_runner.h"
12 #include "base/task/single_thread_task_runner.h"
13 #include "net/base/network_change_notifier.h"
14 #include "net/base/network_change_notifier_factory.h"
15 #include "net/test/test_with_task_environment.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 using ::testing::AtLeast;
20 using ::testing::Invoke;
21 using ::testing::Return;
22 using ::testing::StrictMock;
23 
24 namespace net {
25 
26 // Subclass of NetworkChangeNotifierWin that overrides functions so that no
27 // Windows API networking function results effect tests.
28 class TestNetworkChangeNotifierWin : public NetworkChangeNotifierWin {
29  public:
TestNetworkChangeNotifierWin()30   TestNetworkChangeNotifierWin() {
31     last_computed_connection_type_ = NetworkChangeNotifier::CONNECTION_UNKNOWN;
32     last_announced_offline_ = false;
33     last_computed_connection_cost_ = ConnectionCost::CONNECTION_COST_UNKNOWN;
34     sequence_runner_for_registration_ =
35         base::SequencedTaskRunner::GetCurrentDefault();
36   }
37 
38   TestNetworkChangeNotifierWin(const TestNetworkChangeNotifierWin&) = delete;
39   TestNetworkChangeNotifierWin& operator=(const TestNetworkChangeNotifierWin&) =
40       delete;
41 
~TestNetworkChangeNotifierWin()42   ~TestNetworkChangeNotifierWin() override {
43     // This is needed so we don't try to stop watching for IP address changes,
44     // as we never actually started.
45     set_is_watching(false);
46   }
47 
48   // From NetworkChangeNotifierWin.
RecomputeCurrentConnectionTypeOnBlockingSequence(base::OnceCallback<void (ConnectionType)> reply_callback) const49   void RecomputeCurrentConnectionTypeOnBlockingSequence(
50       base::OnceCallback<void(ConnectionType)> reply_callback) const override {
51     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
52         FROM_HERE, base::BindOnce(std::move(reply_callback),
53                                   NetworkChangeNotifier::CONNECTION_UNKNOWN));
54   }
55 
56   // From NetworkChangeNotifierWin.
57   MOCK_METHOD0(WatchForAddressChangeInternal, bool());
58 };
59 
60 class TestIPAddressObserver : public NetworkChangeNotifier::IPAddressObserver {
61  public:
TestIPAddressObserver()62   TestIPAddressObserver() {
63     NetworkChangeNotifier::AddIPAddressObserver(this);
64   }
65 
66   TestIPAddressObserver(const TestIPAddressObserver&) = delete;
67   TestIPAddressObserver& operator=(const TestIPAddressObserver&) = delete;
68 
~TestIPAddressObserver()69   ~TestIPAddressObserver() override {
70     NetworkChangeNotifier::RemoveIPAddressObserver(this);
71   }
72 
73   MOCK_METHOD0(OnIPAddressChanged, void());
74 };
75 
76 class NetworkChangeNotifierWinTest : public TestWithTaskEnvironment {
77  public:
78   // Calls WatchForAddressChange, and simulates a WatchForAddressChangeInternal
79   // success.  Expects that |network_change_notifier_| has just been created, so
80   // it's not watching anything yet, and there have been no previous
81   // WatchForAddressChangeInternal failures.
StartWatchingAndSucceed()82   void StartWatchingAndSucceed() {
83     EXPECT_FALSE(network_change_notifier_.is_watching());
84     EXPECT_EQ(0, network_change_notifier_.sequential_failures());
85 
86     EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(0);
87     EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal())
88         .Times(1)
89         .WillOnce(Return(true));
90 
91     network_change_notifier_.WatchForAddressChange();
92 
93     EXPECT_TRUE(network_change_notifier_.is_watching());
94     EXPECT_EQ(0, network_change_notifier_.sequential_failures());
95 
96     // If a task to notify observers of the IP address change event was
97     // incorrectly posted, make sure it gets run to trigger a failure.
98     base::RunLoop().RunUntilIdle();
99   }
100 
101   // Calls WatchForAddressChange, and simulates a WatchForAddressChangeInternal
102   // failure.
StartWatchingAndFail()103   void StartWatchingAndFail() {
104     EXPECT_FALSE(network_change_notifier_.is_watching());
105     EXPECT_EQ(0, network_change_notifier_.sequential_failures());
106 
107     EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(0);
108     EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal())
109         // Due to an expected race, it's theoretically possible for more than
110         // one call to occur, though unlikely.
111         .Times(AtLeast(1))
112         .WillRepeatedly(Return(false));
113 
114     network_change_notifier_.WatchForAddressChange();
115 
116     EXPECT_FALSE(network_change_notifier_.is_watching());
117     EXPECT_LT(0, network_change_notifier_.sequential_failures());
118 
119     // If a task to notify observers of the IP address change event was
120     // incorrectly posted, make sure it gets run.
121     base::RunLoop().RunUntilIdle();
122   }
123 
124   // Simulates a network change event, resulting in a call to OnObjectSignaled.
125   // The resulting call to WatchForAddressChangeInternal then succeeds.
SignalAndSucceed()126   void SignalAndSucceed() {
127     EXPECT_TRUE(network_change_notifier_.is_watching());
128     EXPECT_EQ(0, network_change_notifier_.sequential_failures());
129 
130     EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(1);
131     EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal())
132         .Times(1)
133         .WillOnce(Return(true));
134 
135     network_change_notifier_.OnObjectSignaled(INVALID_HANDLE_VALUE);
136 
137     EXPECT_TRUE(network_change_notifier_.is_watching());
138     EXPECT_EQ(0, network_change_notifier_.sequential_failures());
139 
140     // Run the task to notify observers of the IP address change event.
141     base::RunLoop().RunUntilIdle();
142   }
143 
144   // Simulates a network change event, resulting in a call to OnObjectSignaled.
145   // The resulting call to WatchForAddressChangeInternal then fails.
SignalAndFail()146   void SignalAndFail() {
147     EXPECT_TRUE(network_change_notifier_.is_watching());
148     EXPECT_EQ(0, network_change_notifier_.sequential_failures());
149 
150     EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(1);
151     EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal())
152         // Due to an expected race, it's theoretically possible for more than
153         // one call to occur, though unlikely.
154         .Times(AtLeast(1))
155         .WillRepeatedly(Return(false));
156 
157     network_change_notifier_.OnObjectSignaled(INVALID_HANDLE_VALUE);
158 
159     EXPECT_FALSE(network_change_notifier_.is_watching());
160     EXPECT_LT(0, network_change_notifier_.sequential_failures());
161 
162     // Run the task to notify observers of the IP address change event.
163     base::RunLoop().RunUntilIdle();
164   }
165 
166   // Runs the message loop until WatchForAddressChange is called again, as a
167   // result of the already posted task after a WatchForAddressChangeInternal
168   // failure.  Simulates a success on the resulting call to
169   // WatchForAddressChangeInternal.
RetryAndSucceed()170   void RetryAndSucceed() {
171     EXPECT_FALSE(network_change_notifier_.is_watching());
172     EXPECT_LT(0, network_change_notifier_.sequential_failures());
173 
174     base::RunLoop run_loop;
175 
176     EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged())
177         .Times(1)
178         .WillOnce(Invoke(&run_loop, &base::RunLoop::QuitWhenIdle));
179     EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal())
180         .Times(1).WillOnce(Return(true));
181 
182     run_loop.Run();
183 
184     EXPECT_TRUE(network_change_notifier_.is_watching());
185     EXPECT_EQ(0, network_change_notifier_.sequential_failures());
186   }
187 
188   // Runs the message loop until WatchForAddressChange is called again, as a
189   // result of the already posted task after a WatchForAddressChangeInternal
190   // failure.  Simulates a failure on the resulting call to
191   // WatchForAddressChangeInternal.
RetryAndFail()192   void RetryAndFail() {
193     base::RunLoop loop;
194     EXPECT_FALSE(network_change_notifier_.is_watching());
195     EXPECT_LT(0, network_change_notifier_.sequential_failures());
196 
197     int initial_sequential_failures =
198         network_change_notifier_.sequential_failures();
199 
200     EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged()).Times(0);
201     EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal())
202         // Due to an expected race, it's theoretically possible for more than
203         // one call to occur, though unlikely.
204         .Times(AtLeast(1))
205         .WillRepeatedly(Invoke([&loop]() {
206           loop.QuitWhenIdle();
207           return false;
208         }));
209 
210     loop.Run();
211 
212     EXPECT_FALSE(network_change_notifier_.is_watching());
213     EXPECT_LT(initial_sequential_failures,
214               network_change_notifier_.sequential_failures());
215 
216     // If a task to notify observers of the IP address change event was
217     // incorrectly posted, make sure it gets run.
218     base::RunLoop().RunUntilIdle();
219   }
220 
HasNetworkCostManager()221   bool HasNetworkCostManager() {
222     return network_change_notifier_.network_cost_manager_.Get() != nullptr;
223   }
224 
HasNetworkCostManagerEventSink()225   bool HasNetworkCostManagerEventSink() {
226     return network_change_notifier_.network_cost_manager_event_sink_.Get() !=
227            nullptr;
228   }
229 
LastComputedConnectionCost()230   NetworkChangeNotifier::ConnectionCost LastComputedConnectionCost() {
231     return network_change_notifier_.last_computed_connection_cost_;
232   }
233 
GetCurrentConnectionCost()234   NetworkChangeNotifier::ConnectionCost GetCurrentConnectionCost() {
235     return network_change_notifier_.GetCurrentConnectionCost();
236   }
237 
238  private:
239   // Note that the order of declaration here is important.
240 
241   // Allows creating a new NetworkChangeNotifier.  Must be created before
242   // |network_change_notifier_| and destroyed after it to avoid DCHECK failures.
243   NetworkChangeNotifier::DisableForTest disable_for_test_;
244 
245   StrictMock<TestNetworkChangeNotifierWin> network_change_notifier_;
246 
247   // Must be created after |network_change_notifier_|, so it can add itself as
248   // an IPAddressObserver.
249   StrictMock<TestIPAddressObserver> test_ip_address_observer_;
250 };
251 
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinBasic)252 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinBasic) {
253   StartWatchingAndSucceed();
254 }
255 
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailStart)256 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStart) {
257   StartWatchingAndFail();
258 }
259 
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailStartOnce)260 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartOnce) {
261   StartWatchingAndFail();
262   RetryAndSucceed();
263 }
264 
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailStartTwice)265 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartTwice) {
266   StartWatchingAndFail();
267   RetryAndFail();
268   RetryAndSucceed();
269 }
270 
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinSignal)271 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinSignal) {
272   StartWatchingAndSucceed();
273   SignalAndSucceed();
274 }
275 
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailSignalOnce)276 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalOnce) {
277   StartWatchingAndSucceed();
278   SignalAndFail();
279   RetryAndSucceed();
280 }
281 
TEST_F(NetworkChangeNotifierWinTest,NetChangeWinFailSignalTwice)282 TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalTwice) {
283   StartWatchingAndSucceed();
284   SignalAndFail();
285   RetryAndFail();
286   RetryAndSucceed();
287 }
288 
289 class TestConnectionCostObserver
290     : public NetworkChangeNotifier::ConnectionCostObserver {
291  public:
TestConnectionCostObserver()292   TestConnectionCostObserver() {}
293 
294   TestConnectionCostObserver(const TestConnectionCostObserver&) = delete;
295   TestConnectionCostObserver& operator=(const TestConnectionCostObserver&) =
296       delete;
297 
~TestConnectionCostObserver()298   ~TestConnectionCostObserver() override {
299     NetworkChangeNotifier::RemoveConnectionCostObserver(this);
300   }
301 
OnConnectionCostChanged(NetworkChangeNotifier::ConnectionCost)302   void OnConnectionCostChanged(NetworkChangeNotifier::ConnectionCost) override {
303   }
304 
Register()305   void Register() { NetworkChangeNotifier::AddConnectionCostObserver(this); }
306 };
307 
TEST_F(NetworkChangeNotifierWinTest,NetworkCostManagerIntegration)308 TEST_F(NetworkChangeNotifierWinTest, NetworkCostManagerIntegration) {
309   // Upon creation, none of the NetworkCostManager integration should be
310   // initialized yet.
311   ASSERT_FALSE(HasNetworkCostManager());
312   ASSERT_FALSE(HasNetworkCostManagerEventSink());
313   ASSERT_EQ(NetworkChangeNotifier::ConnectionCost::CONNECTION_COST_UNKNOWN,
314             LastComputedConnectionCost());
315 
316   // Asking for the current connection cost should initialize the
317   // NetworkCostManager integration, but not the event sink.
318   // Note that the actual ConnectionCost value return is irrelevant beyond the
319   // fact that it shouldn't be UNKNOWN anymore if the integration is initialized
320   // properly.
321   NetworkChangeNotifier::ConnectionCost current_connection_cost =
322       GetCurrentConnectionCost();
323   EXPECT_NE(NetworkChangeNotifier::ConnectionCost::CONNECTION_COST_UNKNOWN,
324             current_connection_cost);
325   EXPECT_EQ(current_connection_cost, LastComputedConnectionCost());
326   EXPECT_TRUE(HasNetworkCostManager());
327   EXPECT_FALSE(HasNetworkCostManagerEventSink());
328 
329   // Adding a ConnectionCostObserver should initialize the event sink. If the
330   // subsequent registration for updates fails, the event sink will get
331   // destroyed.
332   TestConnectionCostObserver test_connection_cost_observer;
333   test_connection_cost_observer.Register();
334   // The actual registration happens on a callback, so need to run until idle.
335   base::RunLoop().RunUntilIdle();
336   EXPECT_TRUE(HasNetworkCostManagerEventSink());
337 }
338 
339 }  // namespace net
340