Home | History | Annotate | Download | only in base
      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 NetworkChangeNotifierWin.
     34   virtual NetworkChangeNotifier::ConnectionType
     35       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:
     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