Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/link_monitor.h"
     18 
     19 #include <string>
     20 
     21 #include <base/bind.h>
     22 #include <gtest/gtest.h>
     23 
     24 #include "shill/logging.h"
     25 #include "shill/mock_active_link_monitor.h"
     26 #include "shill/mock_connection.h"
     27 #include "shill/mock_control.h"
     28 #include "shill/mock_device_info.h"
     29 #include "shill/mock_event_dispatcher.h"
     30 #include "shill/mock_log.h"
     31 #include "shill/mock_metrics.h"
     32 #include "shill/mock_passive_link_monitor.h"
     33 #include "shill/net/byte_string.h"
     34 #include "shill/net/mock_time.h"
     35 
     36 using base::Bind;
     37 using base::Unretained;
     38 using std::string;
     39 using testing::_;
     40 using testing::AnyNumber;
     41 using testing::HasSubstr;
     42 using testing::Invoke;
     43 using testing::Mock;
     44 using testing::NiceMock;
     45 using testing::Return;
     46 using testing::ReturnRef;
     47 using testing::SetArgumentPointee;
     48 using testing::StrictMock;
     49 using testing::Test;
     50 
     51 namespace shill {
     52 
     53 namespace {
     54 const uint8_t kGatewayMACAddress[] = { 0, 1, 2, 3, 4, 5 };
     55 }  // namespace
     56 
     57 class LinkMonitorObserver {
     58  public:
     59   LinkMonitorObserver()
     60       : failure_callback_(
     61             Bind(&LinkMonitorObserver::OnFailureCallback, Unretained(this))),
     62         gateway_change_callback_(
     63             Bind(&LinkMonitorObserver::OnGatewayChangeCallback,
     64                  Unretained(this))) {}
     65   virtual ~LinkMonitorObserver() {}
     66 
     67   MOCK_METHOD0(OnFailureCallback, void());
     68   MOCK_METHOD0(OnGatewayChangeCallback, void());
     69 
     70   const LinkMonitor::FailureCallback failure_callback() {
     71     return failure_callback_;
     72   }
     73 
     74   const LinkMonitor::GatewayChangeCallback gateway_change_callback() {
     75     return gateway_change_callback_;
     76   }
     77 
     78  private:
     79   LinkMonitor::FailureCallback failure_callback_;
     80   LinkMonitor::GatewayChangeCallback gateway_change_callback_;
     81 
     82   DISALLOW_COPY_AND_ASSIGN(LinkMonitorObserver);
     83 };
     84 
     85 class LinkMonitorTest : public Test {
     86  public:
     87   LinkMonitorTest()
     88       : metrics_(&dispatcher_),
     89         device_info_(&control_, nullptr, nullptr, nullptr),
     90         connection_(new StrictMock<MockConnection>(&device_info_)),
     91         active_link_monitor_(new MockActiveLinkMonitor()),
     92         passive_link_monitor_(new MockPassiveLinkMonitor()),
     93         monitor_(connection_,
     94                  &dispatcher_,
     95                  &metrics_,
     96                  &device_info_,
     97                  observer_.failure_callback(),
     98                  observer_.gateway_change_callback()) {}
     99   virtual ~LinkMonitorTest() {}
    100 
    101   virtual void SetUp() {
    102     monitor_.active_link_monitor_.reset(active_link_monitor_);
    103     monitor_.passive_link_monitor_.reset(passive_link_monitor_);
    104     monitor_.time_ = &time_;
    105 
    106     time_val_.tv_sec = 0;
    107     time_val_.tv_usec = 0;
    108     EXPECT_CALL(time_, GetTimeMonotonic(_))
    109         .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
    110     EXPECT_CALL(*connection_, technology())
    111         .WillRepeatedly(Return(Technology::kEthernet));
    112   }
    113 
    114   void AdvanceTime(int time_ms) {
    115     struct timeval adv_time = {
    116       static_cast<time_t>(time_ms/1000),
    117       static_cast<time_t>((time_ms % 1000) * 1000) };
    118     timeradd(&time_val_, &adv_time, &time_val_);
    119     EXPECT_CALL(time_, GetTimeMonotonic(_))
    120         .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
    121   }
    122 
    123   void SetGatewayMacAddress(const ByteString& gateway_mac_address) {
    124     monitor_.gateway_mac_address_ = gateway_mac_address;
    125   }
    126 
    127   void VerifyGatewayMacAddress(const ByteString& gateway_mac_address) {
    128     EXPECT_TRUE(monitor_.gateway_mac_address_.Equals(gateway_mac_address));
    129   }
    130 
    131   void TriggerActiveLinkMonitorFailure(Metrics::LinkMonitorFailure failure,
    132                                        int broadcast_failure_count,
    133                                        int unicast_failure_count) {
    134     monitor_.OnActiveLinkMonitorFailure(failure,
    135                                     broadcast_failure_count,
    136                                     unicast_failure_count);
    137   }
    138 
    139   void TriggerActiveLinkMonitorSuccess() {
    140     monitor_.OnActiveLinkMonitorSuccess();
    141   }
    142 
    143   void TriggerPassiveLinkMonitorResultCallback(bool status) {
    144     monitor_.OnPassiveLinkMonitorResultCallback(status);
    145   }
    146 
    147  protected:
    148   MockEventDispatcher dispatcher_;
    149   StrictMock<MockMetrics> metrics_;
    150   MockControl control_;
    151   NiceMock<MockDeviceInfo> device_info_;
    152   scoped_refptr<MockConnection> connection_;
    153   MockTime time_;
    154   struct timeval time_val_;
    155   MockActiveLinkMonitor* active_link_monitor_;
    156   MockPassiveLinkMonitor* passive_link_monitor_;
    157   LinkMonitorObserver observer_;
    158   LinkMonitor monitor_;
    159 };
    160 
    161 MATCHER_P(IsMacAddress, mac_address, "") {
    162   return mac_address.Equals(arg);
    163 }
    164 
    165 TEST_F(LinkMonitorTest, Start) {
    166   EXPECT_CALL(*active_link_monitor_,
    167               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds))
    168       .WillOnce(Return(false));
    169   EXPECT_FALSE(monitor_.Start());
    170   Mock::VerifyAndClearExpectations(active_link_monitor_);
    171 
    172   EXPECT_CALL(*active_link_monitor_,
    173               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds))
    174       .WillOnce(Return(true));
    175   EXPECT_TRUE(monitor_.Start());
    176   Mock::VerifyAndClearExpectations(active_link_monitor_);
    177 }
    178 
    179 TEST_F(LinkMonitorTest, OnAfterResume) {
    180   ByteString gateway_mac(kGatewayMACAddress, arraysize(kGatewayMACAddress));
    181   const bool kGatewayUnicastArpSupport = true;
    182   SetGatewayMacAddress(gateway_mac);
    183   // Verify gateway settings persist when link monitor is restarted, and
    184   // active link monitor is started with fast test period.
    185   EXPECT_CALL(*active_link_monitor_, Stop()).Times(1);
    186   EXPECT_CALL(*passive_link_monitor_, Stop()).Times(1);
    187   EXPECT_CALL(*active_link_monitor_, gateway_supports_unicast_arp())
    188       .WillOnce(Return(kGatewayUnicastArpSupport));
    189   EXPECT_CALL(*active_link_monitor_,
    190               set_gateway_mac_address(IsMacAddress(gateway_mac)));
    191   EXPECT_CALL(*active_link_monitor_,
    192               set_gateway_supports_unicast_arp(kGatewayUnicastArpSupport));
    193   EXPECT_CALL(*active_link_monitor_,
    194               Start(ActiveLinkMonitor::kFastTestPeriodMilliseconds));
    195   monitor_.OnAfterResume();
    196   VerifyGatewayMacAddress(gateway_mac);
    197   Mock::VerifyAndClearExpectations(active_link_monitor_);
    198   Mock::VerifyAndClearExpectations(passive_link_monitor_);
    199 }
    200 
    201 TEST_F(LinkMonitorTest, OnActiveLinkMonitorFailure) {
    202   // Start link monitor.
    203   EXPECT_CALL(*active_link_monitor_,
    204               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds))
    205       .WillOnce(Return(true));
    206   EXPECT_TRUE(monitor_.Start());
    207   Mock::VerifyAndClearExpectations(active_link_monitor_);
    208 
    209   const int kBroadcastFailureCount = 5;
    210   const int kUnicastFailureCount = 3;
    211   const int kElapsedTimeMilliseconds = 5000;
    212 
    213   // Active monitor failed after 5 seconds.
    214   EXPECT_CALL(observer_, OnFailureCallback()).Times(1);
    215   EXPECT_CALL(metrics_, SendEnumToUMA(
    216       HasSubstr("LinkMonitorFailure"),
    217       Metrics::kLinkMonitorFailureThresholdReached, _));
    218   EXPECT_CALL(metrics_, SendToUMA(
    219       HasSubstr("LinkMonitorSecondsToFailure"), kElapsedTimeMilliseconds / 1000,
    220       _, _, _));
    221   EXPECT_CALL(metrics_, SendToUMA(
    222       HasSubstr("BroadcastErrorsAtFailure"), kBroadcastFailureCount,
    223       _, _, _));
    224   EXPECT_CALL(metrics_, SendToUMA(
    225       HasSubstr("UnicastErrorsAtFailure"), kUnicastFailureCount,
    226       _, _, _));
    227   AdvanceTime(kElapsedTimeMilliseconds);
    228   TriggerActiveLinkMonitorFailure(Metrics::kLinkMonitorFailureThresholdReached,
    229                                   kBroadcastFailureCount,
    230                                   kUnicastFailureCount);
    231 }
    232 
    233 TEST_F(LinkMonitorTest, OnActiveLinkMonitorSuccess) {
    234   ByteString gateway_mac(kGatewayMACAddress,
    235                                arraysize(kGatewayMACAddress));
    236   EXPECT_CALL(*active_link_monitor_, gateway_mac_address())
    237       .WillRepeatedly(ReturnRef(gateway_mac));
    238 
    239   // Active link monitor succeed for the first time, gateway MAC address will be
    240   // updated.
    241   EXPECT_CALL(observer_, OnGatewayChangeCallback()).Times(1);
    242   EXPECT_CALL(*passive_link_monitor_, Start(
    243       PassiveLinkMonitor::kDefaultMonitorCycles)).Times(1);
    244   TriggerActiveLinkMonitorSuccess();
    245   VerifyGatewayMacAddress(gateway_mac);
    246   Mock::VerifyAndClearExpectations(&observer_);
    247   Mock::VerifyAndClearExpectations(passive_link_monitor_);
    248 
    249   // Active link monitor succeed again, gateway MAC address not changed.
    250   EXPECT_CALL(observer_, OnGatewayChangeCallback()).Times(0);
    251   EXPECT_CALL(*passive_link_monitor_, Start(
    252       PassiveLinkMonitor::kDefaultMonitorCycles)).Times(1);
    253   TriggerActiveLinkMonitorSuccess();
    254   VerifyGatewayMacAddress(gateway_mac);
    255   Mock::VerifyAndClearExpectations(&observer_);
    256   Mock::VerifyAndClearExpectations(passive_link_monitor_);
    257 }
    258 
    259 TEST_F(LinkMonitorTest, OnPassiveLinkMonitorResultCallback) {
    260   // Active link monitor should start regardless of the result of the passive
    261   // link monitor.
    262 
    263   EXPECT_CALL(*active_link_monitor_,
    264               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds));
    265   TriggerPassiveLinkMonitorResultCallback(true);
    266   Mock::VerifyAndClearExpectations(active_link_monitor_);
    267 
    268   EXPECT_CALL(*active_link_monitor_,
    269               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds));
    270   TriggerPassiveLinkMonitorResultCallback(false);
    271   Mock::VerifyAndClearExpectations(active_link_monitor_);
    272 }
    273 
    274 }  // namespace shill
    275