blob: 0bfae8557b92bbd82c8760ea808b249defbe8387 [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, "") {
71 return
72 local_ip.Equals(arg.local_ip_address()) &&
73 remote_ip.Equals(arg.remote_ip_address()) &&
74 local_mac.Equals(arg.local_mac_address()) &&
75 remote_mac.Equals(arg.remote_mac_address());
76}
77
Paul Stewart3f43f432012-07-16 12:12:45 -070078class LinkMonitorTest : public Test {
79 public:
80 LinkMonitorTest()
Thieu Le6c1e3bb2013-02-06 15:20:35 -080081 : metrics_(&dispatcher_),
82 device_info_(
Paul Stewart6c72c972012-07-27 11:29:20 -070083 &control_,
84 reinterpret_cast<EventDispatcher*>(NULL),
85 reinterpret_cast<Metrics*>(NULL),
86 reinterpret_cast<Manager*>(NULL)),
Paul Stewart3f43f432012-07-16 12:12:45 -070087 connection_(new StrictMock<MockConnection>(&device_info_)),
Paul Stewartff845fc2012-08-07 07:28:44 -070088 monitor_(connection_, &dispatcher_, &metrics_, &device_info_),
Paul Stewart6c72c972012-07-27 11:29:20 -070089 client_(NULL),
90 next_client_(new StrictMock<MockArpClient>()),
91 gateway_ip_(IPAddress::kFamilyIPv4),
92 local_ip_(IPAddress::kFamilyIPv4),
93 gateway_mac_(kRemoteMACAddress, arraysize(kRemoteMACAddress)),
94 local_mac_(kLocalMACAddress, arraysize(kLocalMACAddress)),
95 zero_mac_(arraysize(kLocalMACAddress)),
96 link_scope_logging_was_enabled_(false) {}
Paul Stewart3f43f432012-07-16 12:12:45 -070097 virtual ~LinkMonitorTest() {}
98
Paul Stewart6c72c972012-07-27 11:29:20 -070099 virtual void SetUp() {
100 link_scope_logging_was_enabled_ = SLOG_IS_ON(Link, 0);
101 if (!link_scope_logging_was_enabled_) {
102 ScopeLogger::GetInstance()->EnableScopesByName("link");
103 ScopeLogger::GetInstance()->set_verbose_level(4);
104 }
105 monitor_.time_ = &time_;
Paul Stewart0443aa52012-08-09 10:43:50 -0700106 time_val_.tv_sec = 0;
107 time_val_.tv_usec = 0;
Paul Stewart6c72c972012-07-27 11:29:20 -0700108 EXPECT_CALL(time_, GetTimeMonotonic(_))
109 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
110 EXPECT_TRUE(local_ip_.SetAddressFromString(kLocalIPAddress));
111 EXPECT_CALL(*connection_, local()).WillRepeatedly(ReturnRef(local_ip_));
112 EXPECT_TRUE(gateway_ip_.SetAddressFromString(kRemoteIPAddress));
113 EXPECT_CALL(*connection_, gateway()).WillRepeatedly(ReturnRef(gateway_ip_));
Alex Deymofddc09a2013-07-03 18:41:31 -0700114 EXPECT_CALL(*connection_, technology())
115 .WillRepeatedly(Return(Technology::kEthernet));
Paul Stewart6c72c972012-07-27 11:29:20 -0700116 }
117
118 virtual void TearDown() {
119 if (!link_scope_logging_was_enabled_) {
120 ScopeLogger::GetInstance()->EnableScopesByName("-link");
121 ScopeLogger::GetInstance()->set_verbose_level(0);
122 }
123 }
124
Paul Stewartf1961f82012-09-11 20:45:39 -0700125 void AdvanceTime(int time_ms) {
Han Shenfc349252012-08-30 11:36:04 -0700126 struct timeval adv_time = {
127 static_cast<time_t>(time_ms/1000),
128 static_cast<time_t>((time_ms % 1000) * 1000) };
Paul Stewart6c72c972012-07-27 11:29:20 -0700129 timeradd(&time_val_, &adv_time, &time_val_);
130 EXPECT_CALL(time_, GetTimeMonotonic(_))
131 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
132 }
133
134 bool CreateMockClient() {
135 EXPECT_FALSE(monitor_.arp_client_.get());
136 if (client_) {
137 Mock::VerifyAndClearExpectations(client_);
138 }
139 client_ = next_client_;
140 next_client_ = new StrictMock<MockArpClient>();
141 monitor_.arp_client_.reset(client_);
142 return true;
143 }
Paul Stewart3f43f432012-07-16 12:12:45 -0700144
Paul Stewartf1961f82012-09-11 20:45:39 -0700145 string HardwareAddressToString(const ByteString &address) {
146 return LinkMonitor::HardwareAddressToString(address);
147 }
148
Paul Stewart3f43f432012-07-16 12:12:45 -0700149 protected:
Paul Stewart6c72c972012-07-27 11:29:20 -0700150 void ExpectReset() {
151 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
152 EXPECT_FALSE(GetArpClient());
153 EXPECT_TRUE(GetSendRequestCallback().IsCancelled());
154 EXPECT_EQ(0, GetBroadcastFailureCount());
155 EXPECT_EQ(0, GetUnicastFailureCount());
156 EXPECT_FALSE(IsUnicast());
157 }
158 const ArpClient *GetArpClient() { return monitor_.arp_client_.get(); }
159 void TriggerRequestTimer() {
160 GetSendRequestCallback().callback().Run();
161 }
162 const base::CancelableClosure &GetSendRequestCallback() {
163 return monitor_.send_request_callback_;
164 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700165 int GetBroadcastFailureCount() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700166 return monitor_.broadcast_failure_count_;
167 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700168 int GetUnicastFailureCount() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700169 return monitor_.unicast_failure_count_;
170 }
171 bool IsUnicast() { return monitor_.is_unicast_; }
Paul Stewartf1961f82012-09-11 20:45:39 -0700172 int GetTestPeriodMilliseconds() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700173 return LinkMonitor::kTestPeriodMilliseconds;
174 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700175 int GetFailureThreshold() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700176 return LinkMonitor::kFailureThreshold;
177 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700178 int GetMaxResponseSampleFilterDepth() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700179 return LinkMonitor::kMaxResponseSampleFilterDepth;
180 }
181 void ExpectTransmit(bool is_unicast) {
182 const ByteString &destination_mac = is_unicast ? gateway_mac_ : zero_mac_;
183 if (monitor_.arp_client_.get()) {
184 EXPECT_EQ(client_, monitor_.arp_client_.get());
185 EXPECT_CALL(*client_, TransmitRequest(
186 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
187 .WillOnce(Return(true));
188 } else {
189 EXPECT_CALL(monitor_, CreateClient())
190 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
191 EXPECT_CALL(*next_client_, TransmitRequest(
192 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
193 .WillOnce(Return(true));
194 }
195 EXPECT_CALL(dispatcher_, PostDelayedTask(_, GetTestPeriodMilliseconds()));
196 }
197 void SendNextRequest() {
198 EXPECT_CALL(monitor_, CreateClient())
199 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
200 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(true));
201 EXPECT_CALL(dispatcher_, PostDelayedTask(_, GetTestPeriodMilliseconds()));
202 TriggerRequestTimer();
203 }
204 void ExpectNoTransmit() {
205 MockArpClient *client =
206 monitor_.arp_client_.get() ? client_ : next_client_;
207 EXPECT_CALL(*client, TransmitRequest(_)).Times(0);
208 }
209 void StartMonitor() {
210 EXPECT_CALL(device_info_, GetMACAddress(0, _))
211 .WillOnce(DoAll(SetArgumentPointee<1>(local_mac_), Return(true)));
212 ExpectTransmit(false);
213 EXPECT_TRUE(monitor_.Start());
214 EXPECT_TRUE(GetArpClient());
215 EXPECT_FALSE(IsUnicast());
216 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
217 }
218 bool SimulateReceiveReply(ArpPacket *packet, ByteString *sender) {
219 packet->set_local_ip_address(rx_packet_.local_ip_address());
220 packet->set_remote_ip_address(rx_packet_.remote_ip_address());
221 packet->set_local_mac_address(rx_packet_.local_mac_address());
222 packet->set_remote_mac_address(rx_packet_.remote_mac_address());
223 return true;
224 }
225 void ReceiveResponse(const IPAddress &local_ip,
226 const ByteString &local_mac,
227 const IPAddress &remote_ip,
228 const ByteString &remote_mac) {
229 rx_packet_.set_local_ip_address(local_ip);
230 rx_packet_.set_local_mac_address(local_mac);
231 rx_packet_.set_remote_ip_address(remote_ip);
232 rx_packet_.set_remote_mac_address(remote_mac);
233
234 EXPECT_CALL(*client_, ReceiveReply(_, _))
235 .WillOnce(Invoke(this, &LinkMonitorTest::SimulateReceiveReply));
236 monitor_.ReceiveResponse(0);
237 }
238 void ReceiveCorrectResponse() {
Paul Stewart9f7823e2012-08-09 10:58:26 -0700239 ReceiveResponse(gateway_ip_, gateway_mac_, local_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700240 }
241
242 MockEventDispatcher dispatcher_;
Paul Stewartff845fc2012-08-07 07:28:44 -0700243 StrictMock<MockMetrics> metrics_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700244 MockControl control_;
245 NiceMock<MockDeviceInfo> device_info_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700246 scoped_refptr<MockConnection> connection_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700247 StrictMock<LinkMonitorForTest> monitor_;
248 MockTime time_;
249 struct timeval time_val_;
250 // This is owned by the LinkMonitor, and only tracked here for EXPECT*().
251 MockArpClient *client_;
252 // This is owned by the test until it is handed to the LinkMonitorForTest
253 // and placed // in client_ above.
254 MockArpClient *next_client_;
255 IPAddress gateway_ip_;
256 IPAddress local_ip_;
257 ByteString gateway_mac_;
258 ByteString local_mac_;
259 ByteString zero_mac_;
260 ArpPacket rx_packet_;
261 bool link_scope_logging_was_enabled_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700262};
263
Paul Stewart6c72c972012-07-27 11:29:20 -0700264
Paul Stewart3f43f432012-07-16 12:12:45 -0700265TEST_F(LinkMonitorTest, Constructor) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700266 ExpectReset();
267}
268
269TEST_F(LinkMonitorTest, StartFailedGetMACAddress) {
270 ScopedMockLog log;
271 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
272 EXPECT_CALL(log,
273 Log(logging::LOG_ERROR, _,
274 HasSubstr("Could not get local MAC address"))).Times(1);
275 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(false));
Paul Stewartff845fc2012-08-07 07:28:44 -0700276 EXPECT_CALL(metrics_, SendEnumToUMA(
277 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorMacAddressNotFound,
278 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700279 EXPECT_CALL(monitor_, CreateClient()).Times(0);
280 EXPECT_FALSE(monitor_.Start());
281 ExpectReset();
282}
283
284TEST_F(LinkMonitorTest, StartFailedCreateClient) {
285 ScopedMockLog log;
286 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
287 EXPECT_CALL(log,
288 Log(logging::LOG_ERROR, _,
289 HasSubstr("Failed to start ARP client"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700290 EXPECT_CALL(metrics_, SendEnumToUMA(
291 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorClientStartFailure,
292 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700293 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
294 EXPECT_CALL(monitor_, CreateClient()).WillOnce(Return(false));
295 EXPECT_FALSE(monitor_.Start());
296 ExpectReset();
297}
298
299TEST_F(LinkMonitorTest, StartFailedTransmitRequest) {
300 ScopedMockLog log;
301 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
302 EXPECT_CALL(log,
303 Log(logging::LOG_ERROR, _,
304 HasSubstr("Failed to send ARP"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700305 EXPECT_CALL(metrics_, SendEnumToUMA(
306 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorTransmitFailure,
307 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700308 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
309 EXPECT_CALL(monitor_, CreateClient())
310 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
311 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(false));
312 EXPECT_FALSE(monitor_.Start());
313 ExpectReset();
314}
315
316TEST_F(LinkMonitorTest, StartSuccess) {
317 StartMonitor();
318}
319
320TEST_F(LinkMonitorTest, Stop) {
321 StartMonitor();
322 monitor_.Stop();
323 ExpectReset();
324}
325
326TEST_F(LinkMonitorTest, ReplyReception) {
327 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700328 const int kResponseTime = 1234;
Paul Stewart6c72c972012-07-27 11:29:20 -0700329 AdvanceTime(kResponseTime);
330 ScopedMockLog log;
331
332 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
333 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our IP"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700334 ReceiveResponse(gateway_ip_, gateway_mac_, gateway_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700335 Mock::VerifyAndClearExpectations(&log);
336
337 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
338 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our MAC"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700339 ReceiveResponse(gateway_ip_, gateway_mac_, local_ip_, gateway_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700340 Mock::VerifyAndClearExpectations(&log);
341
342 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
343 EXPECT_CALL(log, Log(_, _, HasSubstr("not from the gateway"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700344 ReceiveResponse(local_ip_, gateway_mac_, local_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700345 Mock::VerifyAndClearExpectations(&log);
346
347 EXPECT_TRUE(GetArpClient());
348 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
349 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
350 EXPECT_CALL(log, Log(_, _, HasSubstr("Found gateway"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700351 EXPECT_CALL(metrics_, SendToUMA(
352 HasSubstr("LinkMonitorResponseTimeSample"), kResponseTime,
353 _, _, _)).Times(1);
Paul Stewart6c72c972012-07-27 11:29:20 -0700354 ReceiveCorrectResponse();
355 EXPECT_FALSE(GetArpClient());
356 EXPECT_EQ(kResponseTime, monitor_.GetResponseTimeMilliseconds());
357 EXPECT_TRUE(IsUnicast());
358}
359
360TEST_F(LinkMonitorTest, TimeoutBroadcast) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700361 EXPECT_CALL(metrics_, SendToUMA(
362 HasSubstr("LinkMonitorResponseTimeSample"), GetTestPeriodMilliseconds(),
363 _, _, _)).Times(GetFailureThreshold());
Paul Stewart6c72c972012-07-27 11:29:20 -0700364 StartMonitor();
Paul Stewart0443aa52012-08-09 10:43:50 -0700365 // This value doesn't match real life (the timer in this scenario should
366 // advance by LinkMonitor::kTestPeriodMilliseconds), but this demonstrates
367 // the LinkMonitorSecondsToFailure independent from the response-time
368 // figures.
369 const int kTimeIncrement = 1000;
Paul Stewartf1961f82012-09-11 20:45:39 -0700370 for (int i = 1; i < GetFailureThreshold(); ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700371 ExpectTransmit(false);
Paul Stewart0443aa52012-08-09 10:43:50 -0700372 AdvanceTime(kTimeIncrement);
Paul Stewart6c72c972012-07-27 11:29:20 -0700373 TriggerRequestTimer();
374 EXPECT_FALSE(IsUnicast());
375 EXPECT_EQ(i, GetBroadcastFailureCount());
376 EXPECT_EQ(0, GetUnicastFailureCount());
377 EXPECT_EQ(GetTestPeriodMilliseconds(),
378 monitor_.GetResponseTimeMilliseconds());
379 }
380 ScopedMockLog log;
381 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
382 EXPECT_CALL(log,
383 Log(logging::LOG_ERROR, _,
384 HasSubstr("monitor has reached the failure threshold"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700385 EXPECT_CALL(metrics_, SendEnumToUMA(
386 HasSubstr("LinkMonitorFailure"),
387 Metrics::kLinkMonitorFailureThresholdReached, _));
Paul Stewart0443aa52012-08-09 10:43:50 -0700388 EXPECT_CALL(metrics_, SendToUMA(
389 HasSubstr("LinkMonitorSecondsToFailure"),
390 kTimeIncrement * GetFailureThreshold() / 1000, _, _, _));
391 EXPECT_CALL(metrics_, SendToUMA(
392 HasSubstr("BroadcastErrorsAtFailure"), GetFailureThreshold(), _, _, _));
393 EXPECT_CALL(metrics_, SendToUMA(
394 HasSubstr("UnicastErrorsAtFailure"), 0, _, _, _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700395 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
396 ExpectNoTransmit();
Paul Stewartf1961f82012-09-11 20:45:39 -0700397 EXPECT_CALL(monitor_, FailureCallbackHandler());
Paul Stewart0443aa52012-08-09 10:43:50 -0700398 AdvanceTime(kTimeIncrement);
Paul Stewart6c72c972012-07-27 11:29:20 -0700399 TriggerRequestTimer();
400 ExpectReset();
401}
402
403TEST_F(LinkMonitorTest, TimeoutUnicast) {
404 StartMonitor();
Paul Stewartff845fc2012-08-07 07:28:44 -0700405 // Successful broadcast receptions.
406 EXPECT_CALL(metrics_, SendToUMA(
407 HasSubstr("LinkMonitorResponseTimeSample"), 0, _, _, _))
408 .Times(GetFailureThreshold());
409 // Unsuccessful unicast receptions.
410 EXPECT_CALL(metrics_, SendToUMA(
411 HasSubstr("LinkMonitorResponseTimeSample"), GetTestPeriodMilliseconds(),
412 _, _, _)).Times(GetFailureThreshold());
Paul Stewart6c72c972012-07-27 11:29:20 -0700413 ReceiveCorrectResponse();
Paul Stewartf1961f82012-09-11 20:45:39 -0700414 for (int i = 1; i < GetFailureThreshold(); ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700415 // Failed unicast ARP.
416 ExpectTransmit(true);
417 TriggerRequestTimer();
418
419 // Successful broadcast ARP.
420 ExpectTransmit(false);
421 TriggerRequestTimer();
422 ReceiveCorrectResponse();
423
424 EXPECT_EQ(0, GetBroadcastFailureCount());
425 EXPECT_EQ(i, GetUnicastFailureCount());
426 }
427 // Last unicast ARP transmission.
428 ExpectTransmit(true);
429 TriggerRequestTimer();
430
431 ScopedMockLog log;
432 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
433 EXPECT_CALL(log,
434 Log(logging::LOG_ERROR, _,
435 HasSubstr("monitor has reached the failure threshold"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700436 EXPECT_CALL(metrics_, SendEnumToUMA(
437 HasSubstr("LinkMonitorFailure"),
438 Metrics::kLinkMonitorFailureThresholdReached, _));
Paul Stewart0443aa52012-08-09 10:43:50 -0700439 EXPECT_CALL(metrics_, SendToUMA(
440 HasSubstr("LinkMonitorSecondsToFailure"), 0, _, _, _));
441 EXPECT_CALL(metrics_, SendToUMA(
442 HasSubstr("BroadcastErrorsAtFailure"), 0, _, _, _));
443 EXPECT_CALL(metrics_, SendToUMA(
444 HasSubstr("UnicastErrorsAtFailure"), GetFailureThreshold(), _, _, _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700445 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
446 ExpectNoTransmit();
Paul Stewartf1961f82012-09-11 20:45:39 -0700447 EXPECT_CALL(monitor_, FailureCallbackHandler());
Paul Stewart6c72c972012-07-27 11:29:20 -0700448 TriggerRequestTimer();
449 ExpectReset();
450}
451
452TEST_F(LinkMonitorTest, Average) {
Paul Stewartf1961f82012-09-11 20:45:39 -0700453 const int kSamples[] = { 200, 950, 1200, 4096, 5000,
454 86, 120, 3060, 842, 750 };
455 const size_t filter_depth = GetMaxResponseSampleFilterDepth();
Paul Stewartff845fc2012-08-07 07:28:44 -0700456 EXPECT_CALL(metrics_, SendToUMA(
457 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _))
458 .Times(arraysize(kSamples));
Paul Stewart6c72c972012-07-27 11:29:20 -0700459 ASSERT_GT(arraysize(kSamples), filter_depth);
460 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700461 size_t i = 0;
462 int sum = 0;
Paul Stewart6c72c972012-07-27 11:29:20 -0700463 for (; i < filter_depth; ++i) {
464 AdvanceTime(kSamples[i]);
465 ReceiveCorrectResponse();
466 sum += kSamples[i];
467 EXPECT_EQ(sum / (i + 1), monitor_.GetResponseTimeMilliseconds());
468 SendNextRequest();
469 }
470 for (; i < arraysize(kSamples); ++i) {
471 AdvanceTime(kSamples[i]);
472 ReceiveCorrectResponse();
473 sum = (sum + kSamples[i]) * filter_depth / (filter_depth + 1);
474 EXPECT_EQ(sum / filter_depth, monitor_.GetResponseTimeMilliseconds());
475 SendNextRequest();
476 }
477}
478
479TEST_F(LinkMonitorTest, ImpulseResponse) {
Paul Stewartf1961f82012-09-11 20:45:39 -0700480 const int kNormalValue = 50;
481 const int kExceptionalValue = 5000;
482 const int filter_depth = GetMaxResponseSampleFilterDepth();
Paul Stewartff845fc2012-08-07 07:28:44 -0700483 EXPECT_CALL(metrics_, SendToUMA(
484 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _))
485 .Times(AnyNumber());
Paul Stewart6c72c972012-07-27 11:29:20 -0700486 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700487 for (int i = 0; i < filter_depth * 2; ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700488 AdvanceTime(kNormalValue);
489 ReceiveCorrectResponse();
490 EXPECT_EQ(kNormalValue, monitor_.GetResponseTimeMilliseconds());
491 SendNextRequest();
492 }
493 AdvanceTime(kExceptionalValue);
494 ReceiveCorrectResponse();
495 // Our expectation is that an impulse input will be a
496 // impulse_height / (filter_depth + 1) increase to the running average.
Paul Stewartf1961f82012-09-11 20:45:39 -0700497 int expected_impulse_response =
Paul Stewart6c72c972012-07-27 11:29:20 -0700498 kNormalValue + (kExceptionalValue - kNormalValue) / (filter_depth + 1);
499 EXPECT_EQ(expected_impulse_response, monitor_.GetResponseTimeMilliseconds());
500 SendNextRequest();
501
502 // From here, if we end up continuing to receive normal values, our
503 // running average should decay backwards to the normal value.
Paul Stewartf1961f82012-09-11 20:45:39 -0700504 const int failsafe = 100;
505 int last_value = monitor_.GetResponseTimeMilliseconds();
506 for (int i = 0; i < failsafe && last_value != kNormalValue; ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700507 AdvanceTime(kNormalValue);
508 ReceiveCorrectResponse();
509 // We should advance monotonically (but not necessarily linearly)
510 // back towards the normal value.
511 EXPECT_GE(last_value, monitor_.GetResponseTimeMilliseconds());
512 SendNextRequest();
513 last_value = monitor_.GetResponseTimeMilliseconds();
514 }
515 EXPECT_EQ(kNormalValue, last_value);
Paul Stewart3f43f432012-07-16 12:12:45 -0700516}
517
Paul Stewartf1961f82012-09-11 20:45:39 -0700518TEST_F(LinkMonitorTest, HardwareAddressToString) {
519 const uint8 address0[] = { 0, 1, 2, 3, 4, 5 };
520 EXPECT_EQ("00:01:02:03:04:05",
521 HardwareAddressToString(ByteString(address0, arraysize(address0))));
522 const uint8 address1[] = { 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd };
523 EXPECT_EQ("88:99:aa:bb:cc:dd",
524 HardwareAddressToString(ByteString(address1, arraysize(address1))));
525}
526
Paul Stewart3f43f432012-07-16 12:12:45 -0700527} // namespace shill