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/active_link_monitor.h" 18 19 #include <net/if_arp.h> 20 21 #include <string> 22 23 #include <base/bind.h> 24 #include <gtest/gtest.h> 25 26 #include "shill/arp_client_test_helper.h" 27 #include "shill/arp_packet.h" 28 #include "shill/logging.h" 29 #include "shill/mock_arp_client.h" 30 #include "shill/mock_connection.h" 31 #include "shill/mock_control.h" 32 #include "shill/mock_device_info.h" 33 #include "shill/mock_event_dispatcher.h" 34 #include "shill/mock_log.h" 35 #include "shill/mock_metrics.h" 36 #include "shill/net/byte_string.h" 37 #include "shill/net/ip_address.h" 38 #include "shill/net/mock_sockets.h" 39 #include "shill/net/mock_time.h" 40 41 using base::Bind; 42 using base::Unretained; 43 using std::string; 44 using testing::_; 45 using testing::AnyNumber; 46 using testing::HasSubstr; 47 using testing::Invoke; 48 using testing::Mock; 49 using testing::NiceMock; 50 using testing::Return; 51 using testing::ReturnRef; 52 using testing::SetArgumentPointee; 53 using testing::StrictMock; 54 using testing::Test; 55 56 namespace shill { 57 58 namespace { 59 const char kInterfaceName[] = "int0"; 60 const char kLocalIPAddress[] = "10.0.1.1"; 61 const uint8_t kLocalMACAddress[] = { 0, 1, 2, 3, 4, 5 }; 62 const char kRemoteIPAddress[] = "10.0.1.2"; 63 const uint8_t kRemoteMACAddress[] = { 6, 7, 8, 9, 10, 11 }; 64 const char kDBusPath[] = "/dbus/path"; 65 } // namespace 66 67 68 class ActiveLinkMonitorObserver { 69 public: 70 ActiveLinkMonitorObserver() 71 : failure_callback_( 72 Bind(&ActiveLinkMonitorObserver::OnFailureCallback, 73 Unretained(this))), 74 success_callback_( 75 Bind(&ActiveLinkMonitorObserver::OnSuccessCallback, 76 Unretained(this))) {} 77 virtual ~ActiveLinkMonitorObserver() {} 78 79 MOCK_METHOD3(OnFailureCallback, 80 void(Metrics::LinkMonitorFailure failrue_code, 81 int broadcast_failure_count, 82 int unicast_failure_count)); 83 MOCK_METHOD0(OnSuccessCallback, void()); 84 85 const ActiveLinkMonitor::FailureCallback failure_callback() { 86 return failure_callback_; 87 } 88 89 const ActiveLinkMonitor::SuccessCallback success_callback() { 90 return success_callback_; 91 } 92 93 private: 94 ActiveLinkMonitor::FailureCallback failure_callback_; 95 ActiveLinkMonitor::SuccessCallback success_callback_; 96 97 DISALLOW_COPY_AND_ASSIGN(ActiveLinkMonitorObserver); 98 }; 99 100 MATCHER_P4(IsArpRequest, local_ip, remote_ip, local_mac, remote_mac, "") { 101 if (local_ip.Equals(arg.local_ip_address()) && 102 remote_ip.Equals(arg.remote_ip_address()) && 103 local_mac.Equals(arg.local_mac_address()) && 104 remote_mac.Equals(arg.remote_mac_address())) 105 return true; 106 107 if (!local_ip.Equals(arg.local_ip_address())) { 108 *result_listener << "Local IP '" << arg.local_ip_address().ToString() 109 << "' (wanted '" << local_ip.ToString() << "')."; 110 } 111 112 if (!remote_ip.Equals(arg.remote_ip_address())) { 113 *result_listener << "Remote IP '" << arg.remote_ip_address().ToString() 114 << "' (wanted '" << remote_ip.ToString() << "')."; 115 } 116 117 if (!local_mac.Equals(arg.local_mac_address())) { 118 *result_listener << "Local MAC '" << arg.local_mac_address().HexEncode() 119 << "' (wanted " << local_mac.HexEncode() << ")'."; 120 } 121 122 if (!remote_mac.Equals(arg.remote_mac_address())) { 123 *result_listener << "Remote MAC '" << arg.remote_mac_address().HexEncode() 124 << "' (wanted " << remote_mac.HexEncode() << ")'."; 125 } 126 127 return false; 128 } 129 130 class ActiveLinkMonitorTest : public Test { 131 public: 132 ActiveLinkMonitorTest() 133 : metrics_(&dispatcher_), 134 device_info_(&control_, nullptr, nullptr, nullptr), 135 connection_(new StrictMock<MockConnection>(&device_info_)), 136 client_(new MockArpClient()), 137 client_test_helper_(client_), 138 gateway_ip_(IPAddress::kFamilyIPv4), 139 local_ip_(IPAddress::kFamilyIPv4), 140 gateway_mac_(kRemoteMACAddress, arraysize(kRemoteMACAddress)), 141 local_mac_(kLocalMACAddress, arraysize(kLocalMACAddress)), 142 zero_mac_(arraysize(kLocalMACAddress)), 143 link_scope_logging_was_enabled_(false), 144 interface_name_(kInterfaceName), 145 monitor_(connection_, 146 &dispatcher_, 147 &metrics_, 148 &device_info_, 149 observer_.failure_callback(), 150 observer_.success_callback()) {} 151 virtual ~ActiveLinkMonitorTest() {} 152 153 virtual void SetUp() { 154 link_scope_logging_was_enabled_ = SLOG_IS_ON(Link, 0); 155 if (!link_scope_logging_was_enabled_) { 156 ScopeLogger::GetInstance()->EnableScopesByName("link"); 157 ScopeLogger::GetInstance()->set_verbose_level(4); 158 } 159 monitor_.arp_client_.reset(client_); 160 monitor_.time_ = &time_; 161 time_val_.tv_sec = 0; 162 time_val_.tv_usec = 0; 163 EXPECT_CALL(time_, GetTimeMonotonic(_)) 164 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0))); 165 EXPECT_TRUE(local_ip_.SetAddressFromString(kLocalIPAddress)); 166 EXPECT_CALL(*connection_, local()).WillRepeatedly(ReturnRef(local_ip_)); 167 EXPECT_TRUE(gateway_ip_.SetAddressFromString(kRemoteIPAddress)); 168 EXPECT_CALL(*connection_, gateway()).WillRepeatedly(ReturnRef(gateway_ip_)); 169 EXPECT_CALL(*connection_, technology()) 170 .WillRepeatedly(Return(Technology::kEthernet)); 171 EXPECT_CALL(*connection_, ipconfig_rpc_identifier()) 172 .WillRepeatedly(testing::ReturnPointee(&kDBusPath)); 173 EXPECT_CALL(*connection_, interface_name()) 174 .WillRepeatedly(ReturnRef(interface_name_)); 175 } 176 177 virtual void TearDown() { 178 if (!link_scope_logging_was_enabled_) { 179 ScopeLogger::GetInstance()->EnableScopesByName("-link"); 180 ScopeLogger::GetInstance()->set_verbose_level(0); 181 } 182 } 183 184 void AdvanceTime(int time_ms) { 185 struct timeval adv_time = { 186 static_cast<time_t>(time_ms/1000), 187 static_cast<time_t>((time_ms % 1000) * 1000) }; 188 timeradd(&time_val_, &adv_time, &time_val_); 189 EXPECT_CALL(time_, GetTimeMonotonic(_)) 190 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0))); 191 } 192 193 string HardwareAddressToString(const ByteString& address) { 194 return ActiveLinkMonitor::HardwareAddressToString(address); 195 } 196 197 protected: 198 void ExpectReset() { 199 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds()); 200 EXPECT_TRUE(GetSendRequestCallback().IsCancelled()); 201 EXPECT_EQ(0, GetBroadcastFailureCount()); 202 EXPECT_EQ(0, GetUnicastFailureCount()); 203 EXPECT_EQ(0, GetBroadcastSuccessCount()); 204 EXPECT_EQ(0, GetUnicastSuccessCount()); 205 EXPECT_FALSE(IsUnicast()); 206 EXPECT_FALSE(GatewaySupportsUnicastArp()); 207 } 208 void TriggerRequestTimer() { 209 GetSendRequestCallback().callback().Run(); 210 } 211 const base::CancelableClosure& GetSendRequestCallback() { 212 return monitor_.send_request_callback_; 213 } 214 int GetBroadcastFailureCount() { 215 return monitor_.broadcast_failure_count_; 216 } 217 int GetUnicastFailureCount() { 218 return monitor_.unicast_failure_count_; 219 } 220 int GetBroadcastSuccessCount() { 221 return monitor_.broadcast_success_count_; 222 } 223 int GetUnicastSuccessCount() { 224 return monitor_.unicast_success_count_; 225 } 226 bool IsUnicast() { return monitor_.is_unicast_; } 227 bool GatewaySupportsUnicastArp() { 228 return monitor_.gateway_supports_unicast_arp_; 229 } 230 int GetCurrentTestPeriodMilliseconds() { 231 return monitor_.test_period_milliseconds_; 232 } 233 int GetDefaultTestPeriodMilliseconds() { 234 return ActiveLinkMonitor::kDefaultTestPeriodMilliseconds; 235 } 236 size_t GetFailureThreshold() { 237 return ActiveLinkMonitor::kFailureThreshold; 238 } 239 size_t GetUnicastReplyReliabilityThreshold() { 240 return ActiveLinkMonitor::kUnicastReplyReliabilityThreshold; 241 } 242 int GetFastTestPeriodMilliseconds() { 243 return ActiveLinkMonitor::kFastTestPeriodMilliseconds; 244 } 245 int GetMaxResponseSampleFilterDepth() { 246 return ActiveLinkMonitor::kMaxResponseSampleFilterDepth; 247 } 248 void ExpectTransmit(bool is_unicast, int transmit_period_milliseconds) { 249 const ByteString& destination_mac = is_unicast ? gateway_mac_ : zero_mac_; 250 EXPECT_CALL(*client_, TransmitRequest( 251 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac))) 252 .WillOnce(Return(true)); 253 EXPECT_CALL(dispatcher_, 254 PostDelayedTask(_, transmit_period_milliseconds)); 255 } 256 void SendNextRequest() { 257 EXPECT_CALL(*client_, TransmitRequest(_)).WillOnce(Return(true)); 258 EXPECT_CALL(dispatcher_, 259 PostDelayedTask(_, GetCurrentTestPeriodMilliseconds())); 260 TriggerRequestTimer(); 261 } 262 void ExpectNoTransmit() { 263 EXPECT_CALL(*client_, TransmitRequest(_)).Times(0); 264 } 265 void StartMonitor() { 266 EXPECT_CALL(device_info_, GetMACAddress(0, _)) 267 .WillOnce(DoAll(SetArgumentPointee<1>(local_mac_), Return(true))); 268 EXPECT_CALL(*client_, StartReplyListener()).WillOnce(Return(true)); 269 EXPECT_CALL(dispatcher_, PostTask(_)).Times(1); 270 EXPECT_TRUE(monitor_.Start( 271 ActiveLinkMonitor::kDefaultTestPeriodMilliseconds)); 272 EXPECT_FALSE(GetSendRequestCallback().IsCancelled()); 273 } 274 void ReceiveResponse(uint16_t operation, 275 const IPAddress& local_ip, 276 const ByteString& local_mac, 277 const IPAddress& remote_ip, 278 const ByteString& remote_mac) { 279 client_test_helper_.GeneratePacket(operation, 280 local_ip, 281 local_mac, 282 remote_ip, 283 remote_mac); 284 monitor_.ReceiveResponse(0); 285 } 286 void ReceiveCorrectResponse() { 287 ReceiveResponse(ARPOP_REPLY, gateway_ip_, gateway_mac_, 288 local_ip_, local_mac_); 289 } 290 void ReceiveReplyAndRestartMonitorCycle() { 291 EXPECT_CALL(observer_, OnSuccessCallback()).Times(1); 292 ReceiveCorrectResponse(); 293 Mock::VerifyAndClearExpectations(&observer_); 294 StartMonitor(); 295 } 296 void RunUnicastResponseCycle(int cycle_count, 297 bool should_respond_to_unicast_probes, 298 bool should_count_failures) { 299 // This method expects the ActiveLinkMonitor to be in a state where it 300 // is waiting for a broadcast response. It also returns with the 301 // ActiveLinkMonitor in the same state. 302 // Successful receptions. 303 EXPECT_CALL(metrics_, SendToUMA( 304 HasSubstr("LinkMonitorResponseTimeSample"), 0, _, _, _)) 305 .Times(cycle_count * (should_respond_to_unicast_probes ? 2 : 1)); 306 // Unsuccessful unicast receptions. 307 EXPECT_CALL(metrics_, SendToUMA( 308 HasSubstr("LinkMonitorResponseTimeSample"), 309 GetDefaultTestPeriodMilliseconds(), 310 _, _, _)).Times(cycle_count * 311 (should_respond_to_unicast_probes ? 0 : 1)); 312 313 // Account for any successes / failures before we started. 314 int expected_broadcast_success_count = GetBroadcastSuccessCount(); 315 int expected_unicast_success_count = GetUnicastSuccessCount(); 316 int expected_unicast_failure_count = GetUnicastFailureCount(); 317 318 LOG(INFO) << "RunUnicastResponseCycle: " << cycle_count; 319 320 for (int i = 0; i < cycle_count; ++i) { 321 // Respond to the pending broadcast request. 322 ReceiveReplyAndRestartMonitorCycle(); 323 324 // Unicast ARP. 325 ExpectTransmit(true, GetDefaultTestPeriodMilliseconds()); 326 TriggerRequestTimer(); 327 if (should_respond_to_unicast_probes) { 328 ReceiveReplyAndRestartMonitorCycle(); 329 } 330 331 // Initiate broadcast ARP. 332 ExpectTransmit(false, GetDefaultTestPeriodMilliseconds()); 333 TriggerRequestTimer(); 334 335 ++expected_broadcast_success_count; 336 if (should_respond_to_unicast_probes) { 337 ++expected_unicast_success_count; 338 expected_unicast_failure_count = 0; 339 } else { 340 if (should_count_failures) { 341 ++expected_unicast_failure_count; 342 } 343 expected_unicast_success_count = 0; 344 } 345 EXPECT_EQ(expected_unicast_failure_count, GetUnicastFailureCount()); 346 EXPECT_EQ(expected_unicast_success_count, GetUnicastSuccessCount()); 347 EXPECT_EQ(0, GetBroadcastFailureCount()); 348 EXPECT_EQ(expected_broadcast_success_count, GetBroadcastSuccessCount()); 349 } 350 } 351 352 MockEventDispatcher dispatcher_; 353 StrictMock<MockMetrics> metrics_; 354 MockControl control_; 355 NiceMock<MockDeviceInfo> device_info_; 356 scoped_refptr<MockConnection> connection_; 357 MockTime time_; 358 struct timeval time_val_; 359 // This is owned by the LinkMonitor, and only tracked here for EXPECT*(). 360 MockArpClient* client_; 361 ArpClientTestHelper client_test_helper_; 362 ActiveLinkMonitorObserver observer_; 363 IPAddress gateway_ip_; 364 IPAddress local_ip_; 365 ByteString gateway_mac_; 366 ByteString local_mac_; 367 ByteString zero_mac_; 368 bool link_scope_logging_was_enabled_; 369 const string interface_name_; 370 ActiveLinkMonitor monitor_; 371 }; 372 373 374 TEST_F(ActiveLinkMonitorTest, Constructor) { 375 ExpectReset(); 376 } 377 378 TEST_F(ActiveLinkMonitorTest, StartFailedGetMACAddress) { 379 ScopedMockLog log; 380 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 381 EXPECT_CALL(log, 382 Log(logging::LOG_ERROR, _, 383 HasSubstr("Could not get local MAC address"))).Times(1); 384 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(false)); 385 EXPECT_CALL(metrics_, SendEnumToUMA( 386 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorMacAddressNotFound, 387 _)); 388 EXPECT_CALL(*client_, StartReplyListener()).Times(0); 389 EXPECT_FALSE(monitor_.Start( 390 ActiveLinkMonitor::kDefaultTestPeriodMilliseconds)); 391 ExpectReset(); 392 } 393 394 TEST_F(ActiveLinkMonitorTest, StartFailedArpClient) { 395 ScopedMockLog log; 396 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 397 EXPECT_CALL(log, 398 Log(logging::LOG_ERROR, _, 399 HasSubstr("Failed to start ARP client"))).Times(1); 400 EXPECT_CALL(metrics_, SendEnumToUMA( 401 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorClientStartFailure, 402 _)); 403 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true)); 404 EXPECT_CALL(*client_, StartReplyListener()).WillOnce(Return(false)); 405 EXPECT_FALSE(monitor_.Start( 406 ActiveLinkMonitor::kDefaultTestPeriodMilliseconds)); 407 ExpectReset(); 408 } 409 410 TEST_F(ActiveLinkMonitorTest, StartSuccess) { 411 StartMonitor(); 412 } 413 414 TEST_F(ActiveLinkMonitorTest, Stop) { 415 StartMonitor(); 416 EXPECT_CALL(*client_, Stop()).Times(1); 417 monitor_.Stop(); 418 ExpectReset(); 419 Mock::VerifyAndClearExpectations(client_); 420 } 421 422 TEST_F(ActiveLinkMonitorTest, ReplyReception) { 423 StartMonitor(); 424 const int kResponseTime = 1234; 425 AdvanceTime(kResponseTime); 426 ScopedMockLog log; 427 428 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 429 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our IP"))).Times(1); 430 ReceiveResponse(ARPOP_REPLY, gateway_ip_, gateway_mac_, 431 gateway_ip_, local_mac_); 432 Mock::VerifyAndClearExpectations(&log); 433 434 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 435 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our MAC"))).Times(1); 436 ReceiveResponse(ARPOP_REPLY, gateway_ip_, gateway_mac_, 437 local_ip_, gateway_mac_); 438 Mock::VerifyAndClearExpectations(&log); 439 440 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 441 EXPECT_CALL(log, Log(_, _, HasSubstr("not from the gateway"))).Times(1); 442 ReceiveResponse(ARPOP_REPLY, local_ip_, gateway_mac_, local_ip_, local_mac_); 443 Mock::VerifyAndClearExpectations(&log); 444 445 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 446 EXPECT_CALL(log, Log(_, _, HasSubstr("This is not a reply packet"))).Times(1); 447 ReceiveResponse(ARPOP_REQUEST, gateway_ip_, gateway_mac_, 448 local_ip_, local_mac_); 449 Mock::VerifyAndClearExpectations(&log); 450 451 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds()); 452 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 453 EXPECT_CALL(log, Log(_, _, HasSubstr("Found gateway"))).Times(1); 454 EXPECT_CALL(metrics_, SendToUMA( 455 HasSubstr("LinkMonitorResponseTimeSample"), kResponseTime, 456 _, _, _)).Times(1); 457 EXPECT_CALL(*client_, Stop()).Times(1); 458 EXPECT_CALL(observer_, OnSuccessCallback()).Times(1); 459 ReceiveCorrectResponse(); 460 EXPECT_EQ(kResponseTime, monitor_.GetResponseTimeMilliseconds()); 461 EXPECT_TRUE(IsUnicast()); 462 Mock::VerifyAndClearExpectations(client_); 463 } 464 465 TEST_F(ActiveLinkMonitorTest, TimeoutBroadcast) { 466 EXPECT_CALL(metrics_, SendToUMA( 467 HasSubstr("LinkMonitorResponseTimeSample"), 468 GetDefaultTestPeriodMilliseconds(), 469 _, _, _)).Times(GetFailureThreshold()); 470 StartMonitor(); 471 // This value doesn't match real life (the timer in this scenario 472 // should advance by LinkMonitor::kDefaultTestPeriodMilliseconds), 473 // but this demonstrates the LinkMonitorSecondsToFailure independent 474 // from the response-time figures. 475 const int kTimeIncrement = 1000; 476 // Transmit initial request. 477 ExpectTransmit(false, GetDefaultTestPeriodMilliseconds()); 478 AdvanceTime(kTimeIncrement); 479 TriggerRequestTimer(); 480 for (size_t i = 1; i < GetFailureThreshold(); ++i) { 481 ExpectTransmit(false, GetDefaultTestPeriodMilliseconds()); 482 AdvanceTime(kTimeIncrement); 483 TriggerRequestTimer(); 484 EXPECT_FALSE(IsUnicast()); 485 EXPECT_EQ(i, GetBroadcastFailureCount()); 486 EXPECT_EQ(0, GetUnicastFailureCount()); 487 EXPECT_EQ(0, GetBroadcastSuccessCount()); 488 EXPECT_EQ(0, GetUnicastSuccessCount()); 489 EXPECT_EQ(GetDefaultTestPeriodMilliseconds(), 490 monitor_.GetResponseTimeMilliseconds()); 491 } 492 ScopedMockLog log; 493 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 494 EXPECT_CALL(log, 495 Log(logging::LOG_ERROR, _, 496 HasSubstr("monitor has reached the failure threshold"))).Times(1); 497 EXPECT_CALL(observer_, 498 OnFailureCallback(Metrics::kLinkMonitorFailureThresholdReached, 499 GetFailureThreshold(), 500 0)).Times(1); 501 EXPECT_FALSE(GetSendRequestCallback().IsCancelled()); 502 // Transmit final request. 503 ExpectNoTransmit(); 504 AdvanceTime(kTimeIncrement); 505 TriggerRequestTimer(); 506 ExpectReset(); 507 } 508 509 TEST_F(ActiveLinkMonitorTest, TimeoutUnicast) { 510 StartMonitor(); 511 512 // Setup expectation for Time::GetTimeMonotonic. 513 const int kTimeIncrement = 1000; 514 AdvanceTime(kTimeIncrement); 515 // Initiate a broadcast ARP. 516 ExpectTransmit(false, GetDefaultTestPeriodMilliseconds()); 517 TriggerRequestTimer(); 518 519 ScopedMockLog log; 520 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 521 EXPECT_CALL(log, 522 Log(logging::LOG_ERROR, _, 523 HasSubstr("monitor has reached the failure threshold"))).Times(0); 524 525 // Unicast failures should not cause LinkMonitor errors if we haven't 526 // noted the gateway as reliably replying to unicast ARP messages. Test 527 // this by doing threshold - 1 successful unicast responses, followed 528 // by a ton of unicast failures. 529 // Initiate broadcast ARP. 530 RunUnicastResponseCycle(GetUnicastReplyReliabilityThreshold() - 1, 531 true, false); 532 EXPECT_EQ(GetUnicastReplyReliabilityThreshold() - 1, 533 GetUnicastSuccessCount()); 534 RunUnicastResponseCycle(GetFailureThreshold() + 535 GetUnicastReplyReliabilityThreshold(), false, false); 536 EXPECT_FALSE(GetSendRequestCallback().IsCancelled()); 537 EXPECT_FALSE(GatewaySupportsUnicastArp()); 538 EXPECT_EQ(0, GetUnicastSuccessCount()); 539 EXPECT_EQ(0, GetUnicastFailureCount()); 540 541 // Cross the the unicast reliability threshold. 542 RunUnicastResponseCycle(GetUnicastReplyReliabilityThreshold() - 1, 543 true, false); 544 EXPECT_CALL(log, 545 Log(_, _, HasSubstr("Unicast failures will now count"))); 546 EXPECT_FALSE(GatewaySupportsUnicastArp()); 547 RunUnicastResponseCycle(1, true, false); 548 EXPECT_TRUE(GatewaySupportsUnicastArp()); 549 550 // Induce one less failures than will cause a link monitor failure, and 551 // confirm that these failures are counted. 552 RunUnicastResponseCycle(GetFailureThreshold() - 1, false, true); 553 EXPECT_EQ(GetFailureThreshold() - 1, GetUnicastFailureCount()); 554 555 Mock::VerifyAndClearExpectations(&log); 556 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); 557 558 // Induce a final broadcast success followed by a unicast failure. 559 EXPECT_CALL(metrics_, SendToUMA( 560 HasSubstr("LinkMonitorResponseTimeSample"), 0, _, _, _)); 561 ReceiveReplyAndRestartMonitorCycle(); 562 563 ExpectTransmit(true, GetDefaultTestPeriodMilliseconds()); 564 TriggerRequestTimer(); 565 EXPECT_FALSE(GetSendRequestCallback().IsCancelled()); 566 567 EXPECT_CALL(metrics_, SendToUMA( 568 HasSubstr("LinkMonitorResponseTimeSample"), 569 GetDefaultTestPeriodMilliseconds(), 570 _, _, _)); 571 EXPECT_CALL(log, 572 Log(logging::LOG_ERROR, _, 573 HasSubstr("monitor has reached the failure threshold"))).Times(1); 574 EXPECT_CALL(observer_, 575 OnFailureCallback(Metrics::kLinkMonitorFailureThresholdReached, 576 0, 577 GetFailureThreshold())).Times(1); 578 ExpectNoTransmit(); 579 TriggerRequestTimer(); 580 ExpectReset(); 581 } 582 583 TEST_F(ActiveLinkMonitorTest, Average) { 584 const int kSamples[] = { 200, 950, 1200, 4096, 5000, 585 86, 120, 3060, 842, 750 }; 586 const size_t filter_depth = GetMaxResponseSampleFilterDepth(); 587 EXPECT_CALL(metrics_, SendToUMA( 588 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _)) 589 .Times(arraysize(kSamples)); 590 ASSERT_GT(arraysize(kSamples), filter_depth); 591 StartMonitor(); 592 size_t i = 0; 593 int sum = 0; 594 for (; i < filter_depth; ++i) { 595 AdvanceTime(kSamples[i]); 596 ReceiveReplyAndRestartMonitorCycle(); 597 sum += kSamples[i]; 598 EXPECT_EQ(sum / (i + 1), monitor_.GetResponseTimeMilliseconds()); 599 SendNextRequest(); 600 } 601 for (; i < arraysize(kSamples); ++i) { 602 AdvanceTime(kSamples[i]); 603 ReceiveReplyAndRestartMonitorCycle(); 604 sum = (sum + kSamples[i]) * filter_depth / (filter_depth + 1); 605 EXPECT_EQ(sum / filter_depth, monitor_.GetResponseTimeMilliseconds()); 606 SendNextRequest(); 607 } 608 } 609 610 TEST_F(ActiveLinkMonitorTest, ImpulseResponse) { 611 const int kNormalValue = 50; 612 const int kExceptionalValue = 5000; 613 const int filter_depth = GetMaxResponseSampleFilterDepth(); 614 EXPECT_CALL(metrics_, SendToUMA( 615 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _)) 616 .Times(AnyNumber()); 617 StartMonitor(); 618 for (int i = 0; i < filter_depth * 2; ++i) { 619 AdvanceTime(kNormalValue); 620 ReceiveReplyAndRestartMonitorCycle(); 621 EXPECT_EQ(kNormalValue, monitor_.GetResponseTimeMilliseconds()); 622 SendNextRequest(); 623 } 624 AdvanceTime(kExceptionalValue); 625 ReceiveReplyAndRestartMonitorCycle(); 626 // Our expectation is that an impulse input will be a 627 // impulse_height / (filter_depth + 1) increase to the running average. 628 int expected_impulse_response = 629 kNormalValue + (kExceptionalValue - kNormalValue) / (filter_depth + 1); 630 EXPECT_EQ(expected_impulse_response, monitor_.GetResponseTimeMilliseconds()); 631 SendNextRequest(); 632 633 // From here, if we end up continuing to receive normal values, our 634 // running average should decay backwards to the normal value. 635 const int failsafe = 100; 636 int last_value = monitor_.GetResponseTimeMilliseconds(); 637 for (int i = 0; i < failsafe && last_value != kNormalValue; ++i) { 638 AdvanceTime(kNormalValue); 639 ReceiveReplyAndRestartMonitorCycle(); 640 // We should advance monotonically (but not necessarily linearly) 641 // back towards the normal value. 642 EXPECT_GE(last_value, monitor_.GetResponseTimeMilliseconds()); 643 SendNextRequest(); 644 last_value = monitor_.GetResponseTimeMilliseconds(); 645 } 646 EXPECT_EQ(kNormalValue, last_value); 647 } 648 649 TEST_F(ActiveLinkMonitorTest, HardwareAddressToString) { 650 const uint8_t address0[] = { 0, 1, 2, 3, 4, 5 }; 651 EXPECT_EQ("00:01:02:03:04:05", 652 HardwareAddressToString(ByteString(address0, arraysize(address0)))); 653 const uint8_t address1[] = { 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd }; 654 EXPECT_EQ("88:99:aa:bb:cc:dd", 655 HardwareAddressToString(ByteString(address1, arraysize(address1)))); 656 } 657 658 } // namespace shill 659