blob: 72db7f4134044ef4059a309e43c793d27edf9e09 [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
Paul Stewart6c72c972012-07-27 11:29:20 -07007#include <base/bind.h>
Paul Stewart3f43f432012-07-16 12:12:45 -07008#include <gtest/gtest.h>
9
Paul Stewart6c72c972012-07-27 11:29:20 -070010#include "shill/arp_packet.h"
Paul Stewartf1961f82012-09-11 20:45:39 -070011#include "shill/byte_string.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070012#include "shill/ip_address.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070013#include "shill/logging.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070014#include "shill/mock_arp_client.h"
Paul Stewart3f43f432012-07-16 12:12:45 -070015#include "shill/mock_control.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070016#include "shill/mock_connection.h"
Paul Stewart3f43f432012-07-16 12:12:45 -070017#include "shill/mock_device_info.h"
18#include "shill/mock_event_dispatcher.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070019#include "shill/mock_log.h"
Paul Stewartff845fc2012-08-07 07:28:44 -070020#include "shill/mock_metrics.h"
Paul Stewart3f43f432012-07-16 12:12:45 -070021#include "shill/mock_sockets.h"
Paul Stewart6c72c972012-07-27 11:29:20 -070022#include "shill/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 {
42const int kInterfaceIndex = 123;
43const char kLocalIPAddress[] = "10.0.1.1";
44const uint8 kLocalMACAddress[] = { 0, 1, 2, 3, 4, 5 };
45const char kRemoteIPAddress[] = "10.0.1.2";
46const uint8 kRemoteMACAddress[] = { 6, 7, 8, 9, 10, 11 };
Paul Stewartf1961f82012-09-11 20:45:39 -070047} // namespace
Paul Stewart6c72c972012-07-27 11:29:20 -070048
49
50class LinkMonitorForTest : public LinkMonitor {
51 public:
52 LinkMonitorForTest(const ConnectionRefPtr &connection,
53 EventDispatcher *dispatcher,
Paul Stewartff845fc2012-08-07 07:28:44 -070054 Metrics *metrics,
Paul Stewart6c72c972012-07-27 11:29:20 -070055 DeviceInfo *device_info)
Paul Stewartff845fc2012-08-07 07:28:44 -070056 : LinkMonitor(connection, dispatcher, metrics, device_info,
Paul Stewartf1961f82012-09-11 20:45:39 -070057 Bind(&LinkMonitorForTest::FailureCallbackHandler,
Paul Stewart6c72c972012-07-27 11:29:20 -070058 Unretained(this))) {}
59
60 virtual ~LinkMonitorForTest() {}
61
62 MOCK_METHOD0(CreateClient, bool());
Paul Stewartf1961f82012-09-11 20:45:39 -070063
64 // This does not override any methods in LinkMonitor, but is used here
65 // in unit tests to support expectations when the LinkMonitor notifies
66 // its client of a failure.
67 MOCK_METHOD0(FailureCallbackHandler, void());
Paul Stewart6c72c972012-07-27 11:29:20 -070068};
69
70MATCHER_P4(IsArpRequest, local_ip, remote_ip, local_mac, remote_mac, "") {
mukesh agrawalbb2231c2013-07-17 16:32:24 -070071 if (local_ip.Equals(arg.local_ip_address()) &&
Paul Stewart6c72c972012-07-27 11:29:20 -070072 remote_ip.Equals(arg.remote_ip_address()) &&
73 local_mac.Equals(arg.local_mac_address()) &&
mukesh agrawalbb2231c2013-07-17 16:32:24 -070074 remote_mac.Equals(arg.remote_mac_address()))
75 return true;
76
77 if (!local_ip.Equals(arg.local_ip_address())) {
78 *result_listener << "Local IP '" << arg.local_ip_address().ToString()
79 << "' (wanted '" << local_ip.ToString() << "').";
80 }
81
82 if (!remote_ip.Equals(arg.remote_ip_address())) {
83 *result_listener << "Remote IP '" << arg.remote_ip_address().ToString()
84 << "' (wanted '" << remote_ip.ToString() << "').";
85 }
86
87 if (!local_mac.Equals(arg.local_mac_address())) {
88 *result_listener << "Local MAC '" << arg.local_mac_address().HexEncode()
89 << "' (wanted " << local_mac.HexEncode() << ")'.";
90 }
91
92 if (!remote_mac.Equals(arg.remote_mac_address())) {
93 *result_listener << "Remote MAC '" << arg.remote_mac_address().HexEncode()
94 << "' (wanted " << remote_mac.HexEncode() << ")'.";
95 }
96
97 return false;
Paul Stewart6c72c972012-07-27 11:29:20 -070098}
99
Paul Stewart3f43f432012-07-16 12:12:45 -0700100class LinkMonitorTest : public Test {
101 public:
102 LinkMonitorTest()
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800103 : metrics_(&dispatcher_),
104 device_info_(
Paul Stewart6c72c972012-07-27 11:29:20 -0700105 &control_,
106 reinterpret_cast<EventDispatcher*>(NULL),
107 reinterpret_cast<Metrics*>(NULL),
108 reinterpret_cast<Manager*>(NULL)),
Paul Stewart3f43f432012-07-16 12:12:45 -0700109 connection_(new StrictMock<MockConnection>(&device_info_)),
Paul Stewartff845fc2012-08-07 07:28:44 -0700110 monitor_(connection_, &dispatcher_, &metrics_, &device_info_),
Paul Stewart6c72c972012-07-27 11:29:20 -0700111 client_(NULL),
112 next_client_(new StrictMock<MockArpClient>()),
113 gateway_ip_(IPAddress::kFamilyIPv4),
114 local_ip_(IPAddress::kFamilyIPv4),
115 gateway_mac_(kRemoteMACAddress, arraysize(kRemoteMACAddress)),
116 local_mac_(kLocalMACAddress, arraysize(kLocalMACAddress)),
117 zero_mac_(arraysize(kLocalMACAddress)),
118 link_scope_logging_was_enabled_(false) {}
Paul Stewart3f43f432012-07-16 12:12:45 -0700119 virtual ~LinkMonitorTest() {}
120
Paul Stewart6c72c972012-07-27 11:29:20 -0700121 virtual void SetUp() {
122 link_scope_logging_was_enabled_ = SLOG_IS_ON(Link, 0);
123 if (!link_scope_logging_was_enabled_) {
124 ScopeLogger::GetInstance()->EnableScopesByName("link");
125 ScopeLogger::GetInstance()->set_verbose_level(4);
126 }
127 monitor_.time_ = &time_;
Paul Stewart0443aa52012-08-09 10:43:50 -0700128 time_val_.tv_sec = 0;
129 time_val_.tv_usec = 0;
Paul Stewart6c72c972012-07-27 11:29:20 -0700130 EXPECT_CALL(time_, GetTimeMonotonic(_))
131 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
132 EXPECT_TRUE(local_ip_.SetAddressFromString(kLocalIPAddress));
133 EXPECT_CALL(*connection_, local()).WillRepeatedly(ReturnRef(local_ip_));
134 EXPECT_TRUE(gateway_ip_.SetAddressFromString(kRemoteIPAddress));
135 EXPECT_CALL(*connection_, gateway()).WillRepeatedly(ReturnRef(gateway_ip_));
Alex Deymofddc09a2013-07-03 18:41:31 -0700136 EXPECT_CALL(*connection_, technology())
137 .WillRepeatedly(Return(Technology::kEthernet));
Paul Stewart6c72c972012-07-27 11:29:20 -0700138 }
139
140 virtual void TearDown() {
141 if (!link_scope_logging_was_enabled_) {
142 ScopeLogger::GetInstance()->EnableScopesByName("-link");
143 ScopeLogger::GetInstance()->set_verbose_level(0);
144 }
145 }
146
Paul Stewartf1961f82012-09-11 20:45:39 -0700147 void AdvanceTime(int time_ms) {
Han Shenfc349252012-08-30 11:36:04 -0700148 struct timeval adv_time = {
149 static_cast<time_t>(time_ms/1000),
150 static_cast<time_t>((time_ms % 1000) * 1000) };
Paul Stewart6c72c972012-07-27 11:29:20 -0700151 timeradd(&time_val_, &adv_time, &time_val_);
152 EXPECT_CALL(time_, GetTimeMonotonic(_))
153 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
154 }
155
156 bool CreateMockClient() {
157 EXPECT_FALSE(monitor_.arp_client_.get());
158 if (client_) {
159 Mock::VerifyAndClearExpectations(client_);
160 }
161 client_ = next_client_;
162 next_client_ = new StrictMock<MockArpClient>();
163 monitor_.arp_client_.reset(client_);
164 return true;
165 }
Paul Stewart3f43f432012-07-16 12:12:45 -0700166
Paul Stewartf1961f82012-09-11 20:45:39 -0700167 string HardwareAddressToString(const ByteString &address) {
168 return LinkMonitor::HardwareAddressToString(address);
169 }
170
Paul Stewart3f43f432012-07-16 12:12:45 -0700171 protected:
Paul Stewart6c72c972012-07-27 11:29:20 -0700172 void ExpectReset() {
173 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
174 EXPECT_FALSE(GetArpClient());
175 EXPECT_TRUE(GetSendRequestCallback().IsCancelled());
176 EXPECT_EQ(0, GetBroadcastFailureCount());
177 EXPECT_EQ(0, GetUnicastFailureCount());
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700178 EXPECT_EQ(0, GetBroadcastSuccessCount());
179 EXPECT_EQ(0, GetUnicastSuccessCount());
Paul Stewart6c72c972012-07-27 11:29:20 -0700180 EXPECT_FALSE(IsUnicast());
181 }
182 const ArpClient *GetArpClient() { return monitor_.arp_client_.get(); }
183 void TriggerRequestTimer() {
184 GetSendRequestCallback().callback().Run();
185 }
186 const base::CancelableClosure &GetSendRequestCallback() {
187 return monitor_.send_request_callback_;
188 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700189 int GetBroadcastFailureCount() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700190 return monitor_.broadcast_failure_count_;
191 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700192 int GetUnicastFailureCount() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700193 return monitor_.unicast_failure_count_;
194 }
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700195 int GetBroadcastSuccessCount() {
196 return monitor_.broadcast_success_count_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700197 }
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700198 int GetUnicastSuccessCount() {
199 return monitor_.unicast_success_count_;
200 }
201 bool IsUnicast() { return monitor_.is_unicast_; }
202 int GetCurrentTestPeriodMilliseconds() {
203 return monitor_.test_period_milliseconds_;
204 }
205 int GetDefaultTestPeriodMilliseconds() {
206 return LinkMonitor::kDefaultTestPeriodMilliseconds;
207 }
208 size_t GetFailureThreshold() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700209 return LinkMonitor::kFailureThreshold;
210 }
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700211 int GetFastTestPeriodMilliseconds() {
212 return LinkMonitor::kFastTestPeriodMilliseconds;
213 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700214 int GetMaxResponseSampleFilterDepth() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700215 return LinkMonitor::kMaxResponseSampleFilterDepth;
216 }
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700217 void ExpectTransmit(bool is_unicast, int transmit_period_milliseconds) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700218 const ByteString &destination_mac = is_unicast ? gateway_mac_ : zero_mac_;
219 if (monitor_.arp_client_.get()) {
220 EXPECT_EQ(client_, monitor_.arp_client_.get());
221 EXPECT_CALL(*client_, TransmitRequest(
222 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
223 .WillOnce(Return(true));
224 } else {
225 EXPECT_CALL(monitor_, CreateClient())
226 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
227 EXPECT_CALL(*next_client_, TransmitRequest(
228 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
229 .WillOnce(Return(true));
230 }
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700231 EXPECT_CALL(dispatcher_,
232 PostDelayedTask(_, transmit_period_milliseconds));
Paul Stewart6c72c972012-07-27 11:29:20 -0700233 }
234 void SendNextRequest() {
235 EXPECT_CALL(monitor_, CreateClient())
236 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
237 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(true));
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700238 EXPECT_CALL(dispatcher_,
239 PostDelayedTask(_, GetCurrentTestPeriodMilliseconds()));
Paul Stewart6c72c972012-07-27 11:29:20 -0700240 TriggerRequestTimer();
241 }
242 void ExpectNoTransmit() {
243 MockArpClient *client =
244 monitor_.arp_client_.get() ? client_ : next_client_;
245 EXPECT_CALL(*client, TransmitRequest(_)).Times(0);
246 }
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700247 void ExpectRestart(int transmit_period_milliseconds) {
248 EXPECT_CALL(device_info_, GetMACAddress(0, _))
249 .WillOnce(DoAll(SetArgumentPointee<1>(local_mac_), Return(true)));
250 // Can't just use ExpectTransmit, because that depends on state
251 // that changes during Stop.
252 EXPECT_CALL(monitor_, CreateClient())
253 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
254 EXPECT_CALL(*next_client_, TransmitRequest(
255 IsArpRequest(local_ip_, gateway_ip_, local_mac_, zero_mac_)))
256 .WillOnce(Return(true));
257 EXPECT_CALL(dispatcher_,
258 PostDelayedTask(_, transmit_period_milliseconds));
259 }
Paul Stewart6c72c972012-07-27 11:29:20 -0700260 void StartMonitor() {
261 EXPECT_CALL(device_info_, GetMACAddress(0, _))
262 .WillOnce(DoAll(SetArgumentPointee<1>(local_mac_), Return(true)));
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700263 ExpectTransmit(false, GetDefaultTestPeriodMilliseconds());
Paul Stewart6c72c972012-07-27 11:29:20 -0700264 EXPECT_TRUE(monitor_.Start());
265 EXPECT_TRUE(GetArpClient());
266 EXPECT_FALSE(IsUnicast());
267 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
268 }
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700269 void ReportResume() {
270 monitor_.OnAfterResume();
271 }
Paul Stewart6c72c972012-07-27 11:29:20 -0700272 bool SimulateReceiveReply(ArpPacket *packet, ByteString *sender) {
273 packet->set_local_ip_address(rx_packet_.local_ip_address());
274 packet->set_remote_ip_address(rx_packet_.remote_ip_address());
275 packet->set_local_mac_address(rx_packet_.local_mac_address());
276 packet->set_remote_mac_address(rx_packet_.remote_mac_address());
277 return true;
278 }
279 void ReceiveResponse(const IPAddress &local_ip,
280 const ByteString &local_mac,
281 const IPAddress &remote_ip,
282 const ByteString &remote_mac) {
283 rx_packet_.set_local_ip_address(local_ip);
284 rx_packet_.set_local_mac_address(local_mac);
285 rx_packet_.set_remote_ip_address(remote_ip);
286 rx_packet_.set_remote_mac_address(remote_mac);
287
288 EXPECT_CALL(*client_, ReceiveReply(_, _))
289 .WillOnce(Invoke(this, &LinkMonitorTest::SimulateReceiveReply));
290 monitor_.ReceiveResponse(0);
291 }
292 void ReceiveCorrectResponse() {
Paul Stewart9f7823e2012-08-09 10:58:26 -0700293 ReceiveResponse(gateway_ip_, gateway_mac_, local_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700294 }
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700295 bool IsGatewayFound() {
296 return monitor_.IsGatewayFound();
297 }
Paul Stewart6c72c972012-07-27 11:29:20 -0700298
299 MockEventDispatcher dispatcher_;
Paul Stewartff845fc2012-08-07 07:28:44 -0700300 StrictMock<MockMetrics> metrics_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700301 MockControl control_;
302 NiceMock<MockDeviceInfo> device_info_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700303 scoped_refptr<MockConnection> connection_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700304 StrictMock<LinkMonitorForTest> monitor_;
305 MockTime time_;
306 struct timeval time_val_;
307 // This is owned by the LinkMonitor, and only tracked here for EXPECT*().
308 MockArpClient *client_;
309 // This is owned by the test until it is handed to the LinkMonitorForTest
310 // and placed // in client_ above.
311 MockArpClient *next_client_;
312 IPAddress gateway_ip_;
313 IPAddress local_ip_;
314 ByteString gateway_mac_;
315 ByteString local_mac_;
316 ByteString zero_mac_;
317 ArpPacket rx_packet_;
318 bool link_scope_logging_was_enabled_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700319};
320
Paul Stewart6c72c972012-07-27 11:29:20 -0700321
Paul Stewart3f43f432012-07-16 12:12:45 -0700322TEST_F(LinkMonitorTest, Constructor) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700323 ExpectReset();
324}
325
326TEST_F(LinkMonitorTest, StartFailedGetMACAddress) {
327 ScopedMockLog log;
328 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
329 EXPECT_CALL(log,
330 Log(logging::LOG_ERROR, _,
331 HasSubstr("Could not get local MAC address"))).Times(1);
332 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(false));
Paul Stewartff845fc2012-08-07 07:28:44 -0700333 EXPECT_CALL(metrics_, SendEnumToUMA(
334 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorMacAddressNotFound,
335 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700336 EXPECT_CALL(monitor_, CreateClient()).Times(0);
337 EXPECT_FALSE(monitor_.Start());
338 ExpectReset();
339}
340
341TEST_F(LinkMonitorTest, StartFailedCreateClient) {
342 ScopedMockLog log;
343 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
344 EXPECT_CALL(log,
345 Log(logging::LOG_ERROR, _,
346 HasSubstr("Failed to start ARP client"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700347 EXPECT_CALL(metrics_, SendEnumToUMA(
348 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorClientStartFailure,
349 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700350 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
351 EXPECT_CALL(monitor_, CreateClient()).WillOnce(Return(false));
352 EXPECT_FALSE(monitor_.Start());
353 ExpectReset();
354}
355
356TEST_F(LinkMonitorTest, StartFailedTransmitRequest) {
357 ScopedMockLog log;
358 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
359 EXPECT_CALL(log,
360 Log(logging::LOG_ERROR, _,
361 HasSubstr("Failed to send ARP"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700362 EXPECT_CALL(metrics_, SendEnumToUMA(
363 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorTransmitFailure,
364 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700365 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
366 EXPECT_CALL(monitor_, CreateClient())
367 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
368 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(false));
369 EXPECT_FALSE(monitor_.Start());
370 ExpectReset();
371}
372
373TEST_F(LinkMonitorTest, StartSuccess) {
374 StartMonitor();
375}
376
377TEST_F(LinkMonitorTest, Stop) {
378 StartMonitor();
379 monitor_.Stop();
380 ExpectReset();
381}
382
383TEST_F(LinkMonitorTest, ReplyReception) {
384 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700385 const int kResponseTime = 1234;
Paul Stewart6c72c972012-07-27 11:29:20 -0700386 AdvanceTime(kResponseTime);
387 ScopedMockLog log;
388
389 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
390 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our IP"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700391 ReceiveResponse(gateway_ip_, gateway_mac_, gateway_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700392 Mock::VerifyAndClearExpectations(&log);
393
394 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
395 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our MAC"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700396 ReceiveResponse(gateway_ip_, gateway_mac_, local_ip_, gateway_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700397 Mock::VerifyAndClearExpectations(&log);
398
399 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
400 EXPECT_CALL(log, Log(_, _, HasSubstr("not from the gateway"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700401 ReceiveResponse(local_ip_, gateway_mac_, local_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700402 Mock::VerifyAndClearExpectations(&log);
403
404 EXPECT_TRUE(GetArpClient());
405 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
406 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
407 EXPECT_CALL(log, Log(_, _, HasSubstr("Found gateway"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700408 EXPECT_CALL(metrics_, SendToUMA(
409 HasSubstr("LinkMonitorResponseTimeSample"), kResponseTime,
410 _, _, _)).Times(1);
Paul Stewart6c72c972012-07-27 11:29:20 -0700411 ReceiveCorrectResponse();
412 EXPECT_FALSE(GetArpClient());
413 EXPECT_EQ(kResponseTime, monitor_.GetResponseTimeMilliseconds());
414 EXPECT_TRUE(IsUnicast());
415}
416
417TEST_F(LinkMonitorTest, TimeoutBroadcast) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700418 EXPECT_CALL(metrics_, SendToUMA(
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700419 HasSubstr("LinkMonitorResponseTimeSample"),
420 GetDefaultTestPeriodMilliseconds(),
Paul Stewartff845fc2012-08-07 07:28:44 -0700421 _, _, _)).Times(GetFailureThreshold());
Paul Stewart6c72c972012-07-27 11:29:20 -0700422 StartMonitor();
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700423 // This value doesn't match real life (the timer in this scenario
424 // should advance by LinkMonitor::kDefaultTestPeriodMilliseconds),
425 // but this demonstrates the LinkMonitorSecondsToFailure independent
426 // from the response-time figures.
Paul Stewart0443aa52012-08-09 10:43:50 -0700427 const int kTimeIncrement = 1000;
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700428 for (size_t i = 1; i < GetFailureThreshold(); ++i) {
429 ExpectTransmit(false, GetDefaultTestPeriodMilliseconds());
Paul Stewart0443aa52012-08-09 10:43:50 -0700430 AdvanceTime(kTimeIncrement);
Paul Stewart6c72c972012-07-27 11:29:20 -0700431 TriggerRequestTimer();
432 EXPECT_FALSE(IsUnicast());
433 EXPECT_EQ(i, GetBroadcastFailureCount());
434 EXPECT_EQ(0, GetUnicastFailureCount());
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700435 EXPECT_EQ(0, GetBroadcastSuccessCount());
436 EXPECT_EQ(0, GetUnicastSuccessCount());
437 EXPECT_EQ(GetDefaultTestPeriodMilliseconds(),
Paul Stewart6c72c972012-07-27 11:29:20 -0700438 monitor_.GetResponseTimeMilliseconds());
439 }
440 ScopedMockLog log;
441 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
442 EXPECT_CALL(log,
443 Log(logging::LOG_ERROR, _,
444 HasSubstr("monitor has reached the failure threshold"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700445 EXPECT_CALL(metrics_, SendEnumToUMA(
446 HasSubstr("LinkMonitorFailure"),
447 Metrics::kLinkMonitorFailureThresholdReached, _));
Paul Stewart0443aa52012-08-09 10:43:50 -0700448 EXPECT_CALL(metrics_, SendToUMA(
449 HasSubstr("LinkMonitorSecondsToFailure"),
450 kTimeIncrement * GetFailureThreshold() / 1000, _, _, _));
451 EXPECT_CALL(metrics_, SendToUMA(
452 HasSubstr("BroadcastErrorsAtFailure"), GetFailureThreshold(), _, _, _));
453 EXPECT_CALL(metrics_, SendToUMA(
454 HasSubstr("UnicastErrorsAtFailure"), 0, _, _, _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700455 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
456 ExpectNoTransmit();
Paul Stewartf1961f82012-09-11 20:45:39 -0700457 EXPECT_CALL(monitor_, FailureCallbackHandler());
Paul Stewart0443aa52012-08-09 10:43:50 -0700458 AdvanceTime(kTimeIncrement);
Paul Stewart6c72c972012-07-27 11:29:20 -0700459 TriggerRequestTimer();
460 ExpectReset();
461}
462
463TEST_F(LinkMonitorTest, TimeoutUnicast) {
464 StartMonitor();
Paul Stewartff845fc2012-08-07 07:28:44 -0700465 // Successful broadcast receptions.
466 EXPECT_CALL(metrics_, SendToUMA(
467 HasSubstr("LinkMonitorResponseTimeSample"), 0, _, _, _))
468 .Times(GetFailureThreshold());
469 // Unsuccessful unicast receptions.
470 EXPECT_CALL(metrics_, SendToUMA(
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700471 HasSubstr("LinkMonitorResponseTimeSample"),
472 GetDefaultTestPeriodMilliseconds(),
Paul Stewartff845fc2012-08-07 07:28:44 -0700473 _, _, _)).Times(GetFailureThreshold());
Paul Stewart6c72c972012-07-27 11:29:20 -0700474 ReceiveCorrectResponse();
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700475 for (size_t i = 1; i < GetFailureThreshold(); ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700476 // Failed unicast ARP.
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700477 ExpectTransmit(true, GetDefaultTestPeriodMilliseconds());
Paul Stewart6c72c972012-07-27 11:29:20 -0700478 TriggerRequestTimer();
479
480 // Successful broadcast ARP.
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700481 ExpectTransmit(false, GetDefaultTestPeriodMilliseconds());
Paul Stewart6c72c972012-07-27 11:29:20 -0700482 TriggerRequestTimer();
483 ReceiveCorrectResponse();
484
485 EXPECT_EQ(0, GetBroadcastFailureCount());
486 EXPECT_EQ(i, GetUnicastFailureCount());
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700487 EXPECT_EQ(i+1, GetBroadcastSuccessCount()); // One before loop.
488 EXPECT_EQ(0, GetUnicastSuccessCount());
Paul Stewart6c72c972012-07-27 11:29:20 -0700489 }
490 // Last unicast ARP transmission.
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700491 ExpectTransmit(true, GetDefaultTestPeriodMilliseconds());
Paul Stewart6c72c972012-07-27 11:29:20 -0700492 TriggerRequestTimer();
493
494 ScopedMockLog log;
495 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
496 EXPECT_CALL(log,
497 Log(logging::LOG_ERROR, _,
498 HasSubstr("monitor has reached the failure threshold"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700499 EXPECT_CALL(metrics_, SendEnumToUMA(
500 HasSubstr("LinkMonitorFailure"),
501 Metrics::kLinkMonitorFailureThresholdReached, _));
Paul Stewart0443aa52012-08-09 10:43:50 -0700502 EXPECT_CALL(metrics_, SendToUMA(
503 HasSubstr("LinkMonitorSecondsToFailure"), 0, _, _, _));
504 EXPECT_CALL(metrics_, SendToUMA(
505 HasSubstr("BroadcastErrorsAtFailure"), 0, _, _, _));
506 EXPECT_CALL(metrics_, SendToUMA(
507 HasSubstr("UnicastErrorsAtFailure"), GetFailureThreshold(), _, _, _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700508 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
509 ExpectNoTransmit();
Paul Stewartf1961f82012-09-11 20:45:39 -0700510 EXPECT_CALL(monitor_, FailureCallbackHandler());
Paul Stewart6c72c972012-07-27 11:29:20 -0700511 TriggerRequestTimer();
512 ExpectReset();
513}
514
mukesh agrawalbb2231c2013-07-17 16:32:24 -0700515TEST_F(LinkMonitorTest, OnAfterResume) {
516 const int kFastTestPeriodMilliseconds = GetFastTestPeriodMilliseconds();
517 StartMonitor();
518 Mock::VerifyAndClearExpectations(&monitor_);
519
520 // Resume should preserve the fact that we haven't resolved the gateway's MAC.
521 EXPECT_FALSE(IsGatewayFound());
522 ExpectRestart(kFastTestPeriodMilliseconds);
523 ReportResume();
524 EXPECT_FALSE(IsGatewayFound());
525
526 // After resume, we should use the fast test period...
527 ExpectRestart(kFastTestPeriodMilliseconds);
528 ReportResume();
529 EXPECT_EQ(kFastTestPeriodMilliseconds, GetCurrentTestPeriodMilliseconds());
530
531 // ...and the fast period should be used for reporting failure to UMA...
532 EXPECT_CALL(metrics_, SendToUMA(
533 HasSubstr("LinkMonitorResponseTimeSample"), kFastTestPeriodMilliseconds,
534 _, _, _));
535 ExpectTransmit(false, kFastTestPeriodMilliseconds);
536 TriggerRequestTimer();
537
538 // ...and the period should be reset after correct responses on both
539 // broadcast and unicast.
540 const int kResponseTime = 12;
541 EXPECT_CALL(metrics_, SendToUMA(
542 HasSubstr("LinkMonitorResponseTimeSample"), kResponseTime, _, _, _))
543 .Times(2);
544 AdvanceTime(kResponseTime);
545 ReceiveCorrectResponse();
546 EXPECT_EQ(GetFastTestPeriodMilliseconds(),
547 GetCurrentTestPeriodMilliseconds()); // Don't change yet.
548 ExpectTransmit(true, kFastTestPeriodMilliseconds);
549 TriggerRequestTimer();
550 AdvanceTime(kResponseTime);
551 ReceiveCorrectResponse();
552 EXPECT_EQ(1, GetBroadcastSuccessCount());
553 EXPECT_EQ(1, GetUnicastSuccessCount());
554 EXPECT_EQ(GetDefaultTestPeriodMilliseconds(),
555 GetCurrentTestPeriodMilliseconds());
556
557 // Resume should preserve the fact that we _have_ resolved the gateway's MAC.
558 EXPECT_TRUE(IsGatewayFound());
559 ExpectRestart(kFastTestPeriodMilliseconds);
560 ReportResume();
561 EXPECT_TRUE(IsGatewayFound());
562
563 // Failure should happen just like normal.
564 ExpectRestart(kFastTestPeriodMilliseconds);
565 ReportResume();
566 EXPECT_CALL(metrics_, SendToUMA(
567 HasSubstr("LinkMonitorResponseTimeSample"), kFastTestPeriodMilliseconds,
568 _, _, _))
569 .Times(GetFailureThreshold());
570 EXPECT_CALL(metrics_, SendEnumToUMA(
571 HasSubstr("LinkMonitorFailure"),
572 Metrics::kLinkMonitorFailureThresholdReached, _));
573 EXPECT_CALL(metrics_, SendToUMA(
574 HasSubstr("LinkMonitorSecondsToFailure"), _, _, _, _));
575 EXPECT_CALL(metrics_, SendToUMA(
576 HasSubstr("BroadcastErrorsAtFailure"), GetFailureThreshold() / 2 + 1,
577 _, _, _));
578 EXPECT_CALL(metrics_, SendToUMA(
579 HasSubstr("UnicastErrorsAtFailure"), GetFailureThreshold() / 2,
580 _, _, _));
581 EXPECT_CALL(monitor_, FailureCallbackHandler());
582 bool unicast_probe = true;
583 for (size_t i = 1 ; i < GetFailureThreshold(); ++i) {
584 ExpectTransmit(unicast_probe, GetFastTestPeriodMilliseconds());
585 TriggerRequestTimer();
586 unicast_probe = !unicast_probe;
587 }
588 TriggerRequestTimer();
589 ExpectReset();
590}
591
Paul Stewart6c72c972012-07-27 11:29:20 -0700592TEST_F(LinkMonitorTest, Average) {
Paul Stewartf1961f82012-09-11 20:45:39 -0700593 const int kSamples[] = { 200, 950, 1200, 4096, 5000,
594 86, 120, 3060, 842, 750 };
595 const size_t filter_depth = GetMaxResponseSampleFilterDepth();
Paul Stewartff845fc2012-08-07 07:28:44 -0700596 EXPECT_CALL(metrics_, SendToUMA(
597 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _))
598 .Times(arraysize(kSamples));
Paul Stewart6c72c972012-07-27 11:29:20 -0700599 ASSERT_GT(arraysize(kSamples), filter_depth);
600 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700601 size_t i = 0;
602 int sum = 0;
Paul Stewart6c72c972012-07-27 11:29:20 -0700603 for (; i < filter_depth; ++i) {
604 AdvanceTime(kSamples[i]);
605 ReceiveCorrectResponse();
606 sum += kSamples[i];
607 EXPECT_EQ(sum / (i + 1), monitor_.GetResponseTimeMilliseconds());
608 SendNextRequest();
609 }
610 for (; i < arraysize(kSamples); ++i) {
611 AdvanceTime(kSamples[i]);
612 ReceiveCorrectResponse();
613 sum = (sum + kSamples[i]) * filter_depth / (filter_depth + 1);
614 EXPECT_EQ(sum / filter_depth, monitor_.GetResponseTimeMilliseconds());
615 SendNextRequest();
616 }
617}
618
619TEST_F(LinkMonitorTest, ImpulseResponse) {
Paul Stewartf1961f82012-09-11 20:45:39 -0700620 const int kNormalValue = 50;
621 const int kExceptionalValue = 5000;
622 const int filter_depth = GetMaxResponseSampleFilterDepth();
Paul Stewartff845fc2012-08-07 07:28:44 -0700623 EXPECT_CALL(metrics_, SendToUMA(
624 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _))
625 .Times(AnyNumber());
Paul Stewart6c72c972012-07-27 11:29:20 -0700626 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700627 for (int i = 0; i < filter_depth * 2; ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700628 AdvanceTime(kNormalValue);
629 ReceiveCorrectResponse();
630 EXPECT_EQ(kNormalValue, monitor_.GetResponseTimeMilliseconds());
631 SendNextRequest();
632 }
633 AdvanceTime(kExceptionalValue);
634 ReceiveCorrectResponse();
635 // Our expectation is that an impulse input will be a
636 // impulse_height / (filter_depth + 1) increase to the running average.
Paul Stewartf1961f82012-09-11 20:45:39 -0700637 int expected_impulse_response =
Paul Stewart6c72c972012-07-27 11:29:20 -0700638 kNormalValue + (kExceptionalValue - kNormalValue) / (filter_depth + 1);
639 EXPECT_EQ(expected_impulse_response, monitor_.GetResponseTimeMilliseconds());
640 SendNextRequest();
641
642 // From here, if we end up continuing to receive normal values, our
643 // running average should decay backwards to the normal value.
Paul Stewartf1961f82012-09-11 20:45:39 -0700644 const int failsafe = 100;
645 int last_value = monitor_.GetResponseTimeMilliseconds();
646 for (int i = 0; i < failsafe && last_value != kNormalValue; ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700647 AdvanceTime(kNormalValue);
648 ReceiveCorrectResponse();
649 // We should advance monotonically (but not necessarily linearly)
650 // back towards the normal value.
651 EXPECT_GE(last_value, monitor_.GetResponseTimeMilliseconds());
652 SendNextRequest();
653 last_value = monitor_.GetResponseTimeMilliseconds();
654 }
655 EXPECT_EQ(kNormalValue, last_value);
Paul Stewart3f43f432012-07-16 12:12:45 -0700656}
657
Paul Stewartf1961f82012-09-11 20:45:39 -0700658TEST_F(LinkMonitorTest, HardwareAddressToString) {
659 const uint8 address0[] = { 0, 1, 2, 3, 4, 5 };
660 EXPECT_EQ("00:01:02:03:04:05",
661 HardwareAddressToString(ByteString(address0, arraysize(address0))));
662 const uint8 address1[] = { 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd };
663 EXPECT_EQ("88:99:aa:bb:cc:dd",
664 HardwareAddressToString(ByteString(address1, arraysize(address1))));
665}
666
Paul Stewart3f43f432012-07-16 12:12:45 -0700667} // namespace shill