Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2015 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/passive_link_monitor.h"
     18 
     19 #include <net/if_arp.h>
     20 
     21 #include <string>
     22 
     23 #include <gtest/gtest.h>
     24 
     25 #include "shill/arp_client_test_helper.h"
     26 #include "shill/arp_packet.h"
     27 #include "shill/logging.h"
     28 #include "shill/mock_arp_client.h"
     29 #include "shill/mock_connection.h"
     30 #include "shill/mock_control.h"
     31 #include "shill/mock_device_info.h"
     32 #include "shill/mock_event_dispatcher.h"
     33 #include "shill/mock_log.h"
     34 #include "shill/net/byte_string.h"
     35 #include "shill/net/ip_address.h"
     36 
     37 using base::Bind;
     38 using base::Unretained;
     39 using std::string;
     40 using testing::_;
     41 using testing::AnyNumber;
     42 using testing::HasSubstr;
     43 using testing::Mock;
     44 using testing::NiceMock;
     45 using testing::Return;
     46 using testing::ReturnRef;
     47 using testing::StrictMock;
     48 using testing::Test;
     49 
     50 namespace shill {
     51 
     52 namespace {
     53 const char kInterfaceName[] = "test-interface";
     54 const char kLocalIPAddress[] = "10.0.1.1";
     55 const uint8_t kLocalMACAddress[] = { 0, 1, 2, 3, 4, 5 };
     56 const char kRemoteIPAddress[] = "10.0.1.2";
     57 const uint8_t kRemoteMACAddress[] = { 6, 7, 8, 9, 10, 11 };
     58 }  // namespace
     59 
     60 class ResultCallbackObserver {
     61  public:
     62   ResultCallbackObserver()
     63       : result_callback_(
     64           Bind(&ResultCallbackObserver::OnResultCallback,
     65                Unretained(this))) {}
     66   virtual ~ResultCallbackObserver() {}
     67 
     68   MOCK_METHOD1(OnResultCallback, void(bool status));
     69 
     70   const PassiveLinkMonitor::ResultCallback result_callback() {
     71     return result_callback_;
     72   }
     73 
     74  private:
     75   PassiveLinkMonitor::ResultCallback result_callback_;
     76 
     77   DISALLOW_COPY_AND_ASSIGN(ResultCallbackObserver);
     78 };
     79 
     80 class PassiveLinkMonitorTest : public Test {
     81  public:
     82   PassiveLinkMonitorTest()
     83       : device_info_(&control_, nullptr, nullptr, nullptr),
     84         connection_(new StrictMock<MockConnection>(&device_info_)),
     85         client_(new MockArpClient()),
     86         client_test_helper_(client_),
     87         link_monitor_(connection_, &dispatcher_, observer_.result_callback()),
     88         interface_name_(kInterfaceName) {}
     89   virtual ~PassiveLinkMonitorTest() {}
     90 
     91   virtual void SetUp() {
     92     ScopeLogger::GetInstance()->EnableScopesByName("link");
     93     ScopeLogger::GetInstance()->set_verbose_level(4);
     94     link_monitor_.arp_client_.reset(client_);
     95 
     96     EXPECT_CALL(*connection_, interface_name())
     97         .WillRepeatedly(ReturnRef(interface_name_));
     98   }
     99 
    100   virtual void TearDown() {
    101     ScopeLogger::GetInstance()->EnableScopesByName("-link");
    102     ScopeLogger::GetInstance()->set_verbose_level(0);
    103   }
    104 
    105   void ReceiveArpPacket(uint16_t operation) {
    106     client_test_helper_.GeneratePacket(
    107         operation,
    108         IPAddress(kLocalIPAddress),
    109         ByteString(kLocalMACAddress, arraysize(kLocalMACAddress)),
    110         IPAddress(kRemoteIPAddress),
    111         ByteString(kRemoteMACAddress, arraysize(kRemoteMACAddress)));
    112     link_monitor_.ReceiveRequest(0);
    113   }
    114 
    115   void MonitorCompleted(bool status) {
    116     link_monitor_.MonitorCompleted(status);
    117   }
    118 
    119   void InvokeCycleTimeoutHandler() {
    120     link_monitor_.CycleTimeoutHandler();
    121   }
    122 
    123   void SetCurrentCycleStats(int num_requests_received, int num_cycles_passed) {
    124     link_monitor_.num_requests_received_ = num_requests_received;
    125     link_monitor_.num_cycles_passed_ = num_cycles_passed;
    126   }
    127 
    128   void VerifyCurrentCycleStats(int num_requests_received,
    129                                int num_cycles_passed) {
    130     EXPECT_EQ(num_requests_received, link_monitor_.num_requests_received_);
    131     EXPECT_EQ(num_cycles_passed, link_monitor_.num_cycles_passed_);
    132   }
    133 
    134  protected:
    135   MockEventDispatcher dispatcher_;
    136   MockControl control_;
    137   NiceMock<MockDeviceInfo> device_info_;
    138   ResultCallbackObserver observer_;
    139   scoped_refptr<MockConnection> connection_;
    140   MockArpClient* client_;
    141   ArpClientTestHelper client_test_helper_;
    142   PassiveLinkMonitor link_monitor_;
    143   const string interface_name_;
    144 };
    145 
    146 TEST_F(PassiveLinkMonitorTest, StartFailedArpClient) {
    147   EXPECT_CALL(*client_, StartRequestListener()).WillOnce(Return(false));
    148   EXPECT_FALSE(link_monitor_.Start(PassiveLinkMonitor::kDefaultMonitorCycles));
    149 }
    150 
    151 TEST_F(PassiveLinkMonitorTest, StartSuccess) {
    152   EXPECT_CALL(*client_, StartRequestListener()).WillOnce(Return(true));
    153   EXPECT_CALL(dispatcher_, CreateReadyHandler(_, IOHandler::kModeInput, _))
    154       .Times(1);
    155   EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(1);
    156   EXPECT_TRUE(link_monitor_.Start(PassiveLinkMonitor::kDefaultMonitorCycles));
    157 }
    158 
    159 TEST_F(PassiveLinkMonitorTest, Stop) {
    160   EXPECT_CALL(*client_, Stop()).Times(1);
    161   link_monitor_.Stop();
    162   Mock::VerifyAndClearExpectations(client_);
    163 }
    164 
    165 TEST_F(PassiveLinkMonitorTest, MonitorCompleted) {
    166   // Monitor failed.
    167   EXPECT_CALL(*client_, Stop()).Times(1);
    168   EXPECT_CALL(observer_, OnResultCallback(false)).Times(1);
    169   MonitorCompleted(false);
    170   Mock::VerifyAndClearExpectations(client_);
    171   Mock::VerifyAndClearExpectations(&observer_);
    172 
    173   // Monitor succeed.
    174   EXPECT_CALL(*client_, Stop()).Times(1);
    175   EXPECT_CALL(observer_, OnResultCallback(true)).Times(1);
    176   MonitorCompleted(true);
    177   Mock::VerifyAndClearExpectations(client_);
    178   Mock::VerifyAndClearExpectations(&observer_);
    179 }
    180 
    181 TEST_F(PassiveLinkMonitorTest, ReceiveArpReply) {
    182   // Setup initial stats.
    183   const int kRequestReceived = 0;
    184   const int kCurrentCycle = 0;
    185   SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
    186   ScopedMockLog log;
    187   EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
    188   EXPECT_CALL(log, Log(_, _, HasSubstr("This is not a request packet")))
    189       .Times(1);
    190   ReceiveArpPacket(ARPOP_REPLY);
    191   // Verify no change in receive count.
    192   VerifyCurrentCycleStats(kRequestReceived, kCurrentCycle);
    193   Mock::VerifyAndClearExpectations(&log);
    194 }
    195 
    196 TEST_F(PassiveLinkMonitorTest, ReceiveArpRequest) {
    197   // Setup initial stats.
    198   const int kRequestReceived = 0;
    199   const int kCurrentCycle = 0;
    200   SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
    201 
    202   EXPECT_CALL(*client_, Stop()).Times(0);
    203   ReceiveArpPacket(ARPOP_REQUEST);
    204   ReceiveArpPacket(ARPOP_REQUEST);
    205   VerifyCurrentCycleStats(kRequestReceived + 2, kCurrentCycle);
    206   Mock::VerifyAndClearExpectations(client_);
    207 }
    208 
    209 TEST_F(PassiveLinkMonitorTest, ReceiveAllRequestsForCycle) {
    210   // 4 ARP requests received in the current cycle so far.
    211   const int kRequestReceived = 4;
    212   const int kCurrentCycle = 0;
    213   SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
    214 
    215   // Received all required requests for a cycle, stop the ARP client.
    216   EXPECT_CALL(*client_, Stop()).Times(1);
    217   ReceiveArpPacket(ARPOP_REQUEST);
    218   Mock::VerifyAndClearExpectations(client_);
    219 }
    220 
    221 TEST_F(PassiveLinkMonitorTest, CycleFailed) {
    222   // 3 ARP requests received in the current cycle so far.
    223   const int kRequestReceived = 3;
    224   const int kCurrentCycle = 0;
    225   SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
    226 
    227   // Monitor failed for the current cycle, post a task to perform cleanup and
    228   // invoke result callback.
    229   EXPECT_CALL(*client_, StartRequestListener()).Times(0);
    230   EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
    231   EXPECT_CALL(dispatcher_, PostTask(_)).Times(1);
    232   InvokeCycleTimeoutHandler();
    233 }
    234 
    235 TEST_F(PassiveLinkMonitorTest, CycleSucceed) {
    236   // 5 ARP requests received in the current cycle so far.
    237   const int kRequestReceived = 5;
    238   const int kCurrentCycle = 0;
    239   SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
    240 
    241   // Monitor succeed for the current cycle, post a task to trigger a new cycle.
    242   EXPECT_CALL(*client_, StartRequestListener()).WillOnce(Return(true));
    243   EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(1);
    244   EXPECT_CALL(dispatcher_, PostTask(_)).Times(0);
    245   InvokeCycleTimeoutHandler();
    246   // ARP request received count should be resetted.
    247   VerifyCurrentCycleStats(0, kCurrentCycle + 1);
    248 }
    249 
    250 TEST_F(PassiveLinkMonitorTest, AllCyclesCompleted) {
    251   // 5 ARP requests received in the current cycle so far.
    252   const int kRequestReceived = 5;
    253   const int kCurrentCycle = PassiveLinkMonitor::kDefaultMonitorCycles - 1;
    254   SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
    255 
    256   // Monitor completed all the cycles, post a task to perform cleanup and
    257   // invoke result callback.
    258   EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
    259   EXPECT_CALL(dispatcher_, PostTask(_)).Times(1);
    260   InvokeCycleTimeoutHandler();
    261   VerifyCurrentCycleStats(0, PassiveLinkMonitor::kDefaultMonitorCycles);
    262 }
    263 
    264 }  // namespace shill
    265