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