network_change_notifier_win_unittest.cc 12 KB

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