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