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
41using base::Bind;
42using base::Unretained;
43using std::string;
44using testing::_;
45using testing::AnyNumber;
46using testing::HasSubstr;
47using testing::Invoke;
48using testing::Mock;
49using testing::NiceMock;
50using testing::Return;
51using testing::ReturnRef;
52using testing::SetArgumentPointee;
53using testing::StrictMock;
54using testing::Test;
55
56namespace shill {
57
58namespace {
59const char kInterfaceName[] = "int0";
60const char kLocalIPAddress[] = "10.0.1.1";
61const uint8_t kLocalMACAddress[] = { 0, 1, 2, 3, 4, 5 };
62const char kRemoteIPAddress[] = "10.0.1.2";
63const uint8_t kRemoteMACAddress[] = { 6, 7, 8, 9, 10, 11 };
64const char kDBusPath[] = "/dbus/path";
65}  // namespace
66
67
68class 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
100MATCHER_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
130class 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
374TEST_F(ActiveLinkMonitorTest, Constructor) {
375  ExpectReset();
376}
377
378TEST_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
394TEST_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
410TEST_F(ActiveLinkMonitorTest, StartSuccess) {
411  StartMonitor();
412}
413
414TEST_F(ActiveLinkMonitorTest, Stop) {
415  StartMonitor();
416  EXPECT_CALL(*client_, Stop()).Times(1);
417  monitor_.Stop();
418  ExpectReset();
419  Mock::VerifyAndClearExpectations(client_);
420}
421
422TEST_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
465TEST_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
509TEST_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
583TEST_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
610TEST_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
649TEST_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