blob: 1b11b3b74347656cbc773c69cedd544a6025722e [file] [log] [blame]
Paul Stewart3f43f432012-07-16 12:12:45 -07001// Copyright (c) 2012 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/link_monitor.h"
6
Alex Vakulenko8a532292014-06-16 17:18:44 -07007#include <string>
8
Paul Stewart6c72c972012-07-27 11:29:20 -07009#include <base/bind.h>
Paul Stewart3f43f432012-07-16 12:12:45 -070010#include <gtest/gtest.h>
11
Christopher Wileyb691efd2012-08-09 13:51:51 -070012#include "shill/logging.h"
Peter Qiuffa56372015-01-22 14:25:23 -080013#include "shill/mock_active_link_monitor.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070014#include "shill/mock_connection.h"
Alex Vakulenkoa41ab512014-07-23 14:24:23 -070015#include "shill/mock_control.h"
Paul Stewart3f43f432012-07-16 12:12:45 -070016#include "shill/mock_device_info.h"
17#include "shill/mock_event_dispatcher.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070018#include "shill/mock_log.h"
Paul Stewartff845fc2012-08-07 07:28:44 -070019#include "shill/mock_metrics.h"
Peter Qiuffa56372015-01-22 14:25:23 -080020#include "shill/mock_passive_link_monitor.h"
Peter Qiu8d6b5972014-10-28 15:33:34 -070021#include "shill/net/byte_string.h"
Peter Qiu8d6b5972014-10-28 15:33:34 -070022#include "shill/net/mock_time.h"
Paul Stewart3f43f432012-07-16 12:12:45 -070023
Paul Stewart6c72c972012-07-27 11:29:20 -070024using base::Bind;
25using base::Unretained;
Paul Stewartf1961f82012-09-11 20:45:39 -070026using std::string;
Paul Stewart6c72c972012-07-27 11:29:20 -070027using testing::_;
28using testing::AnyNumber;
29using testing::HasSubstr;
30using testing::Invoke;
31using testing::Mock;
32using testing::NiceMock;
33using testing::Return;
34using testing::ReturnRef;
35using testing::SetArgumentPointee;
Paul Stewart3f43f432012-07-16 12:12:45 -070036using testing::StrictMock;
37using testing::Test;
38
39namespace shill {
40
Paul Stewart6c72c972012-07-27 11:29:20 -070041namespace {
Peter Qiuffa56372015-01-22 14:25:23 -080042const uint8_t kGatewayMACAddress[] = { 0, 1, 2, 3, 4, 5 };
Paul Stewartf1961f82012-09-11 20:45:39 -070043} // namespace
Paul Stewart6c72c972012-07-27 11:29:20 -070044
Peter Qiuffa56372015-01-22 14:25:23 -080045class LinkMonitorObserver {
Paul Stewart6c72c972012-07-27 11:29:20 -070046 public:
Peter Qiuffa56372015-01-22 14:25:23 -080047 LinkMonitorObserver()
48 : failure_callback_(
49 Bind(&LinkMonitorObserver::OnFailureCallback, Unretained(this))),
50 gateway_change_callback_(
51 Bind(&LinkMonitorObserver::OnGatewayChangeCallback,
52 Unretained(this))) {}
53 virtual ~LinkMonitorObserver() {}
Paul Stewart6c72c972012-07-27 11:29:20 -070054
Peter Qiuffa56372015-01-22 14:25:23 -080055 MOCK_METHOD0(OnFailureCallback, void());
56 MOCK_METHOD0(OnGatewayChangeCallback, void());
Paul Stewart6c72c972012-07-27 11:29:20 -070057
Peter Qiuffa56372015-01-22 14:25:23 -080058 const LinkMonitor::FailureCallback failure_callback() {
59 return failure_callback_;
60 }
Paul Stewartf1961f82012-09-11 20:45:39 -070061
Peter Qiuffa56372015-01-22 14:25:23 -080062 const LinkMonitor::GatewayChangeCallback gateway_change_callback() {
63 return gateway_change_callback_;
64 }
Peter Qiub5d124f2014-04-14 12:05:02 -070065
Peter Qiuffa56372015-01-22 14:25:23 -080066 private:
67 LinkMonitor::FailureCallback failure_callback_;
68 LinkMonitor::GatewayChangeCallback gateway_change_callback_;
69
70 DISALLOW_COPY_AND_ASSIGN(LinkMonitorObserver);
Paul Stewart6c72c972012-07-27 11:29:20 -070071};
72
Paul Stewart3f43f432012-07-16 12:12:45 -070073class LinkMonitorTest : public Test {
74 public:
75 LinkMonitorTest()
Thieu Le6c1e3bb2013-02-06 15:20:35 -080076 : metrics_(&dispatcher_),
Ben Chancc225ef2014-09-30 13:26:51 -070077 device_info_(&control_, nullptr, nullptr, nullptr),
Paul Stewart3f43f432012-07-16 12:12:45 -070078 connection_(new StrictMock<MockConnection>(&device_info_)),
Peter Qiuffa56372015-01-22 14:25:23 -080079 active_link_monitor_(new MockActiveLinkMonitor()),
80 passive_link_monitor_(new MockPassiveLinkMonitor()),
81 monitor_(connection_,
82 &dispatcher_,
83 &metrics_,
84 &device_info_,
85 observer_.failure_callback(),
86 observer_.gateway_change_callback()) {}
Paul Stewart3f43f432012-07-16 12:12:45 -070087 virtual ~LinkMonitorTest() {}
88
Paul Stewart6c72c972012-07-27 11:29:20 -070089 virtual void SetUp() {
Peter Qiuffa56372015-01-22 14:25:23 -080090 monitor_.active_link_monitor_.reset(active_link_monitor_);
91 monitor_.passive_link_monitor_.reset(passive_link_monitor_);
Paul Stewart6c72c972012-07-27 11:29:20 -070092 monitor_.time_ = &time_;
Peter Qiuffa56372015-01-22 14:25:23 -080093
Paul Stewart0443aa52012-08-09 10:43:50 -070094 time_val_.tv_sec = 0;
95 time_val_.tv_usec = 0;
Paul Stewart6c72c972012-07-27 11:29:20 -070096 EXPECT_CALL(time_, GetTimeMonotonic(_))
97 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
Alex Deymofddc09a2013-07-03 18:41:31 -070098 EXPECT_CALL(*connection_, technology())
99 .WillRepeatedly(Return(Technology::kEthernet));
Paul Stewart6c72c972012-07-27 11:29:20 -0700100 }
101
Paul Stewartf1961f82012-09-11 20:45:39 -0700102 void AdvanceTime(int time_ms) {
Han Shenfc349252012-08-30 11:36:04 -0700103 struct timeval adv_time = {
104 static_cast<time_t>(time_ms/1000),
105 static_cast<time_t>((time_ms % 1000) * 1000) };
Paul Stewart6c72c972012-07-27 11:29:20 -0700106 timeradd(&time_val_, &adv_time, &time_val_);
107 EXPECT_CALL(time_, GetTimeMonotonic(_))
108 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
109 }
110
Paul Stewart3b30ca52015-06-16 13:13:10 -0700111 void SetGatewayMacAddress(const ByteString& gateway_mac_address) {
Peter Qiuffa56372015-01-22 14:25:23 -0800112 monitor_.gateway_mac_address_ = gateway_mac_address;
Paul Stewart6c72c972012-07-27 11:29:20 -0700113 }
Paul Stewart3f43f432012-07-16 12:12:45 -0700114
Paul Stewart3b30ca52015-06-16 13:13:10 -0700115 void VerifyGatewayMacAddress(const ByteString& gateway_mac_address) {
Peter Qiuffa56372015-01-22 14:25:23 -0800116 EXPECT_TRUE(monitor_.gateway_mac_address_.Equals(gateway_mac_address));
117 }
118
119 void TriggerActiveLinkMonitorFailure(Metrics::LinkMonitorFailure failure,
120 int broadcast_failure_count,
121 int unicast_failure_count) {
122 monitor_.OnActiveLinkMonitorFailure(failure,
123 broadcast_failure_count,
124 unicast_failure_count);
125 }
126
127 void TriggerActiveLinkMonitorSuccess() {
128 monitor_.OnActiveLinkMonitorSuccess();
129 }
130
131 void TriggerPassiveLinkMonitorResultCallback(bool status) {
132 monitor_.OnPassiveLinkMonitorResultCallback(status);
Paul Stewartf1961f82012-09-11 20:45:39 -0700133 }
134
Paul Stewart3f43f432012-07-16 12:12:45 -0700135 protected:
Paul Stewart6c72c972012-07-27 11:29:20 -0700136 MockEventDispatcher dispatcher_;
Paul Stewartff845fc2012-08-07 07:28:44 -0700137 StrictMock<MockMetrics> metrics_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700138 MockControl control_;
139 NiceMock<MockDeviceInfo> device_info_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700140 scoped_refptr<MockConnection> connection_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700141 MockTime time_;
142 struct timeval time_val_;
Paul Stewart3b30ca52015-06-16 13:13:10 -0700143 MockActiveLinkMonitor* active_link_monitor_;
144 MockPassiveLinkMonitor* passive_link_monitor_;
Peter Qiuffa56372015-01-22 14:25:23 -0800145 LinkMonitorObserver observer_;
146 LinkMonitor monitor_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700147};
148
Peter Qiuffa56372015-01-22 14:25:23 -0800149MATCHER_P(IsMacAddress, mac_address, "") {
150 return mac_address.Equals(arg);
Paul Stewart6c72c972012-07-27 11:29:20 -0700151}
152
Peter Qiuffa56372015-01-22 14:25:23 -0800153TEST_F(LinkMonitorTest, Start) {
154 EXPECT_CALL(*active_link_monitor_,
155 Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds))
156 .WillOnce(Return(false));
Paul Stewart6c72c972012-07-27 11:29:20 -0700157 EXPECT_FALSE(monitor_.Start());
Peter Qiuffa56372015-01-22 14:25:23 -0800158 Mock::VerifyAndClearExpectations(active_link_monitor_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700159
Peter Qiuffa56372015-01-22 14:25:23 -0800160 EXPECT_CALL(*active_link_monitor_,
161 Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds))
162 .WillOnce(Return(true));
163 EXPECT_TRUE(monitor_.Start());
164 Mock::VerifyAndClearExpectations(active_link_monitor_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700165}
166
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700167TEST_F(LinkMonitorTest, OnAfterResume) {
Peter Qiuffa56372015-01-22 14:25:23 -0800168 ByteString gateway_mac(kGatewayMACAddress, arraysize(kGatewayMACAddress));
169 const bool kGatewayUnicastArpSupport = true;
170 SetGatewayMacAddress(gateway_mac);
171 // Verify gateway settings persist when link monitor is restarted, and
172 // active link monitor is started with fast test period.
173 EXPECT_CALL(*active_link_monitor_, Stop()).Times(1);
174 EXPECT_CALL(*passive_link_monitor_, Stop()).Times(1);
175 EXPECT_CALL(*active_link_monitor_, gateway_supports_unicast_arp())
176 .WillOnce(Return(kGatewayUnicastArpSupport));
177 EXPECT_CALL(*active_link_monitor_,
178 set_gateway_mac_address(IsMacAddress(gateway_mac)));
179 EXPECT_CALL(*active_link_monitor_,
180 set_gateway_supports_unicast_arp(kGatewayUnicastArpSupport));
181 EXPECT_CALL(*active_link_monitor_,
182 Start(ActiveLinkMonitor::kFastTestPeriodMilliseconds));
183 monitor_.OnAfterResume();
184 VerifyGatewayMacAddress(gateway_mac);
185 Mock::VerifyAndClearExpectations(active_link_monitor_);
186 Mock::VerifyAndClearExpectations(passive_link_monitor_);
187}
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700188
Peter Qiuffa56372015-01-22 14:25:23 -0800189TEST_F(LinkMonitorTest, OnActiveLinkMonitorFailure) {
190 // Start link monitor.
191 EXPECT_CALL(*active_link_monitor_,
192 Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds))
193 .WillOnce(Return(true));
194 EXPECT_TRUE(monitor_.Start());
195 Mock::VerifyAndClearExpectations(active_link_monitor_);
Paul Stewartb434ce52013-09-23 13:53:49 -0700196
Peter Qiuffa56372015-01-22 14:25:23 -0800197 const int kBroadcastFailureCount = 5;
198 const int kUnicastFailureCount = 3;
199 const int kElapsedTimeMilliseconds = 5000;
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700200
Peter Qiuffa56372015-01-22 14:25:23 -0800201 // Active monitor failed after 5 seconds.
202 EXPECT_CALL(observer_, OnFailureCallback()).Times(1);
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700203 EXPECT_CALL(metrics_, SendEnumToUMA(
204 HasSubstr("LinkMonitorFailure"),
205 Metrics::kLinkMonitorFailureThresholdReached, _));
206 EXPECT_CALL(metrics_, SendToUMA(
Peter Qiuffa56372015-01-22 14:25:23 -0800207 HasSubstr("LinkMonitorSecondsToFailure"), kElapsedTimeMilliseconds / 1000,
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700208 _, _, _));
209 EXPECT_CALL(metrics_, SendToUMA(
Peter Qiuffa56372015-01-22 14:25:23 -0800210 HasSubstr("BroadcastErrorsAtFailure"), kBroadcastFailureCount,
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700211 _, _, _));
Paul Stewartb434ce52013-09-23 13:53:49 -0700212 EXPECT_CALL(metrics_, SendToUMA(
Peter Qiuffa56372015-01-22 14:25:23 -0800213 HasSubstr("UnicastErrorsAtFailure"), kUnicastFailureCount,
Paul Stewartb434ce52013-09-23 13:53:49 -0700214 _, _, _));
Peter Qiuffa56372015-01-22 14:25:23 -0800215 AdvanceTime(kElapsedTimeMilliseconds);
216 TriggerActiveLinkMonitorFailure(Metrics::kLinkMonitorFailureThresholdReached,
217 kBroadcastFailureCount,
218 kUnicastFailureCount);
Paul Stewartb434ce52013-09-23 13:53:49 -0700219}
220
Peter Qiuffa56372015-01-22 14:25:23 -0800221TEST_F(LinkMonitorTest, OnActiveLinkMonitorSuccess) {
222 ByteString gateway_mac(kGatewayMACAddress,
223 arraysize(kGatewayMACAddress));
224 EXPECT_CALL(*active_link_monitor_, gateway_mac_address())
225 .WillRepeatedly(ReturnRef(gateway_mac));
226
227 // Active link monitor succeed for the first time, gateway MAC address will be
228 // updated.
229 EXPECT_CALL(observer_, OnGatewayChangeCallback()).Times(1);
230 EXPECT_CALL(*passive_link_monitor_, Start(
231 PassiveLinkMonitor::kDefaultMonitorCycles)).Times(1);
232 TriggerActiveLinkMonitorSuccess();
233 VerifyGatewayMacAddress(gateway_mac);
234 Mock::VerifyAndClearExpectations(&observer_);
235 Mock::VerifyAndClearExpectations(passive_link_monitor_);
236
237 // Active link monitor succeed again, gateway MAC address not changed.
238 EXPECT_CALL(observer_, OnGatewayChangeCallback()).Times(0);
239 EXPECT_CALL(*passive_link_monitor_, Start(
240 PassiveLinkMonitor::kDefaultMonitorCycles)).Times(1);
241 TriggerActiveLinkMonitorSuccess();
242 VerifyGatewayMacAddress(gateway_mac);
243 Mock::VerifyAndClearExpectations(&observer_);
244 Mock::VerifyAndClearExpectations(passive_link_monitor_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700245}
246
Peter Qiuffa56372015-01-22 14:25:23 -0800247TEST_F(LinkMonitorTest, OnPassiveLinkMonitorResultCallback) {
248 // Active link monitor should start regardless of the result of the passive
249 // link monitor.
Paul Stewart6c72c972012-07-27 11:29:20 -0700250
Peter Qiuffa56372015-01-22 14:25:23 -0800251 EXPECT_CALL(*active_link_monitor_,
252 Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds));
253 TriggerPassiveLinkMonitorResultCallback(true);
254 Mock::VerifyAndClearExpectations(active_link_monitor_);
Paul Stewart3f43f432012-07-16 12:12:45 -0700255
Peter Qiuffa56372015-01-22 14:25:23 -0800256 EXPECT_CALL(*active_link_monitor_,
257 Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds));
258 TriggerPassiveLinkMonitorResultCallback(false);
259 Mock::VerifyAndClearExpectations(active_link_monitor_);
Paul Stewartf1961f82012-09-11 20:45:39 -0700260}
261
Paul Stewart3f43f432012-07-16 12:12:45 -0700262} // namespace shill