blob: 8c5f24956a139a80e9471e943753c6f9b0e247ca [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_));
114 }
115
116 virtual void TearDown() {
117 if (!link_scope_logging_was_enabled_) {
118 ScopeLogger::GetInstance()->EnableScopesByName("-link");
119 ScopeLogger::GetInstance()->set_verbose_level(0);
120 }
121 }
122
Paul Stewartf1961f82012-09-11 20:45:39 -0700123 void AdvanceTime(int time_ms) {
Han Shenfc349252012-08-30 11:36:04 -0700124 struct timeval adv_time = {
125 static_cast<time_t>(time_ms/1000),
126 static_cast<time_t>((time_ms % 1000) * 1000) };
Paul Stewart6c72c972012-07-27 11:29:20 -0700127 timeradd(&time_val_, &adv_time, &time_val_);
128 EXPECT_CALL(time_, GetTimeMonotonic(_))
129 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
130 }
131
132 bool CreateMockClient() {
133 EXPECT_FALSE(monitor_.arp_client_.get());
134 if (client_) {
135 Mock::VerifyAndClearExpectations(client_);
136 }
137 client_ = next_client_;
138 next_client_ = new StrictMock<MockArpClient>();
139 monitor_.arp_client_.reset(client_);
140 return true;
141 }
Paul Stewart3f43f432012-07-16 12:12:45 -0700142
Paul Stewartf1961f82012-09-11 20:45:39 -0700143 string HardwareAddressToString(const ByteString &address) {
144 return LinkMonitor::HardwareAddressToString(address);
145 }
146
Paul Stewart3f43f432012-07-16 12:12:45 -0700147 protected:
Paul Stewart6c72c972012-07-27 11:29:20 -0700148 void ExpectReset() {
149 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
150 EXPECT_FALSE(GetArpClient());
151 EXPECT_TRUE(GetSendRequestCallback().IsCancelled());
152 EXPECT_EQ(0, GetBroadcastFailureCount());
153 EXPECT_EQ(0, GetUnicastFailureCount());
154 EXPECT_FALSE(IsUnicast());
155 }
156 const ArpClient *GetArpClient() { return monitor_.arp_client_.get(); }
157 void TriggerRequestTimer() {
158 GetSendRequestCallback().callback().Run();
159 }
160 const base::CancelableClosure &GetSendRequestCallback() {
161 return monitor_.send_request_callback_;
162 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700163 int GetBroadcastFailureCount() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700164 return monitor_.broadcast_failure_count_;
165 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700166 int GetUnicastFailureCount() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700167 return monitor_.unicast_failure_count_;
168 }
169 bool IsUnicast() { return monitor_.is_unicast_; }
Paul Stewartf1961f82012-09-11 20:45:39 -0700170 int GetTestPeriodMilliseconds() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700171 return LinkMonitor::kTestPeriodMilliseconds;
172 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700173 int GetFailureThreshold() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700174 return LinkMonitor::kFailureThreshold;
175 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700176 int GetMaxResponseSampleFilterDepth() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700177 return LinkMonitor::kMaxResponseSampleFilterDepth;
178 }
179 void ExpectTransmit(bool is_unicast) {
180 const ByteString &destination_mac = is_unicast ? gateway_mac_ : zero_mac_;
181 if (monitor_.arp_client_.get()) {
182 EXPECT_EQ(client_, monitor_.arp_client_.get());
183 EXPECT_CALL(*client_, TransmitRequest(
184 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
185 .WillOnce(Return(true));
186 } else {
187 EXPECT_CALL(monitor_, CreateClient())
188 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
189 EXPECT_CALL(*next_client_, TransmitRequest(
190 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
191 .WillOnce(Return(true));
192 }
193 EXPECT_CALL(dispatcher_, PostDelayedTask(_, GetTestPeriodMilliseconds()));
194 }
195 void SendNextRequest() {
196 EXPECT_CALL(monitor_, CreateClient())
197 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
198 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(true));
199 EXPECT_CALL(dispatcher_, PostDelayedTask(_, GetTestPeriodMilliseconds()));
200 TriggerRequestTimer();
201 }
202 void ExpectNoTransmit() {
203 MockArpClient *client =
204 monitor_.arp_client_.get() ? client_ : next_client_;
205 EXPECT_CALL(*client, TransmitRequest(_)).Times(0);
206 }
207 void StartMonitor() {
208 EXPECT_CALL(device_info_, GetMACAddress(0, _))
209 .WillOnce(DoAll(SetArgumentPointee<1>(local_mac_), Return(true)));
210 ExpectTransmit(false);
211 EXPECT_TRUE(monitor_.Start());
212 EXPECT_TRUE(GetArpClient());
213 EXPECT_FALSE(IsUnicast());
214 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
215 }
216 bool SimulateReceiveReply(ArpPacket *packet, ByteString *sender) {
217 packet->set_local_ip_address(rx_packet_.local_ip_address());
218 packet->set_remote_ip_address(rx_packet_.remote_ip_address());
219 packet->set_local_mac_address(rx_packet_.local_mac_address());
220 packet->set_remote_mac_address(rx_packet_.remote_mac_address());
221 return true;
222 }
223 void ReceiveResponse(const IPAddress &local_ip,
224 const ByteString &local_mac,
225 const IPAddress &remote_ip,
226 const ByteString &remote_mac) {
227 rx_packet_.set_local_ip_address(local_ip);
228 rx_packet_.set_local_mac_address(local_mac);
229 rx_packet_.set_remote_ip_address(remote_ip);
230 rx_packet_.set_remote_mac_address(remote_mac);
231
232 EXPECT_CALL(*client_, ReceiveReply(_, _))
233 .WillOnce(Invoke(this, &LinkMonitorTest::SimulateReceiveReply));
234 monitor_.ReceiveResponse(0);
235 }
236 void ReceiveCorrectResponse() {
Paul Stewart9f7823e2012-08-09 10:58:26 -0700237 ReceiveResponse(gateway_ip_, gateway_mac_, local_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700238 }
239
240 MockEventDispatcher dispatcher_;
Paul Stewartff845fc2012-08-07 07:28:44 -0700241 StrictMock<MockMetrics> metrics_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700242 MockControl control_;
243 NiceMock<MockDeviceInfo> device_info_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700244 scoped_refptr<MockConnection> connection_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700245 StrictMock<LinkMonitorForTest> monitor_;
246 MockTime time_;
247 struct timeval time_val_;
248 // This is owned by the LinkMonitor, and only tracked here for EXPECT*().
249 MockArpClient *client_;
250 // This is owned by the test until it is handed to the LinkMonitorForTest
251 // and placed // in client_ above.
252 MockArpClient *next_client_;
253 IPAddress gateway_ip_;
254 IPAddress local_ip_;
255 ByteString gateway_mac_;
256 ByteString local_mac_;
257 ByteString zero_mac_;
258 ArpPacket rx_packet_;
259 bool link_scope_logging_was_enabled_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700260};
261
Paul Stewart6c72c972012-07-27 11:29:20 -0700262
Paul Stewart3f43f432012-07-16 12:12:45 -0700263TEST_F(LinkMonitorTest, Constructor) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700264 ExpectReset();
265}
266
267TEST_F(LinkMonitorTest, StartFailedGetMACAddress) {
268 ScopedMockLog log;
269 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
270 EXPECT_CALL(log,
271 Log(logging::LOG_ERROR, _,
272 HasSubstr("Could not get local MAC address"))).Times(1);
273 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(false));
Paul Stewartff845fc2012-08-07 07:28:44 -0700274 EXPECT_CALL(metrics_, SendEnumToUMA(
275 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorMacAddressNotFound,
276 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700277 EXPECT_CALL(monitor_, CreateClient()).Times(0);
278 EXPECT_FALSE(monitor_.Start());
279 ExpectReset();
280}
281
282TEST_F(LinkMonitorTest, StartFailedCreateClient) {
283 ScopedMockLog log;
284 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
285 EXPECT_CALL(log,
286 Log(logging::LOG_ERROR, _,
287 HasSubstr("Failed to start ARP client"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700288 EXPECT_CALL(metrics_, SendEnumToUMA(
289 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorClientStartFailure,
290 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700291 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
292 EXPECT_CALL(monitor_, CreateClient()).WillOnce(Return(false));
293 EXPECT_FALSE(monitor_.Start());
294 ExpectReset();
295}
296
297TEST_F(LinkMonitorTest, StartFailedTransmitRequest) {
298 ScopedMockLog log;
299 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
300 EXPECT_CALL(log,
301 Log(logging::LOG_ERROR, _,
302 HasSubstr("Failed to send ARP"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700303 EXPECT_CALL(metrics_, SendEnumToUMA(
304 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorTransmitFailure,
305 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700306 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
307 EXPECT_CALL(monitor_, CreateClient())
308 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
309 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(false));
310 EXPECT_FALSE(monitor_.Start());
311 ExpectReset();
312}
313
314TEST_F(LinkMonitorTest, StartSuccess) {
315 StartMonitor();
316}
317
318TEST_F(LinkMonitorTest, Stop) {
319 StartMonitor();
320 monitor_.Stop();
321 ExpectReset();
322}
323
324TEST_F(LinkMonitorTest, ReplyReception) {
325 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700326 const int kResponseTime = 1234;
Paul Stewart6c72c972012-07-27 11:29:20 -0700327 AdvanceTime(kResponseTime);
328 ScopedMockLog log;
329
330 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
331 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our IP"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700332 ReceiveResponse(gateway_ip_, gateway_mac_, gateway_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700333 Mock::VerifyAndClearExpectations(&log);
334
335 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
336 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our MAC"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700337 ReceiveResponse(gateway_ip_, gateway_mac_, local_ip_, gateway_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700338 Mock::VerifyAndClearExpectations(&log);
339
340 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
341 EXPECT_CALL(log, Log(_, _, HasSubstr("not from the gateway"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700342 ReceiveResponse(local_ip_, gateway_mac_, local_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700343 Mock::VerifyAndClearExpectations(&log);
344
345 EXPECT_TRUE(GetArpClient());
346 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
347 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
348 EXPECT_CALL(log, Log(_, _, HasSubstr("Found gateway"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700349 EXPECT_CALL(metrics_, SendToUMA(
350 HasSubstr("LinkMonitorResponseTimeSample"), kResponseTime,
351 _, _, _)).Times(1);
Paul Stewart6c72c972012-07-27 11:29:20 -0700352 ReceiveCorrectResponse();
353 EXPECT_FALSE(GetArpClient());
354 EXPECT_EQ(kResponseTime, monitor_.GetResponseTimeMilliseconds());
355 EXPECT_TRUE(IsUnicast());
356}
357
358TEST_F(LinkMonitorTest, TimeoutBroadcast) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700359 EXPECT_CALL(metrics_, SendToUMA(
360 HasSubstr("LinkMonitorResponseTimeSample"), GetTestPeriodMilliseconds(),
361 _, _, _)).Times(GetFailureThreshold());
Paul Stewart6c72c972012-07-27 11:29:20 -0700362 StartMonitor();
Paul Stewart0443aa52012-08-09 10:43:50 -0700363 // This value doesn't match real life (the timer in this scenario should
364 // advance by LinkMonitor::kTestPeriodMilliseconds), but this demonstrates
365 // the LinkMonitorSecondsToFailure independent from the response-time
366 // figures.
367 const int kTimeIncrement = 1000;
Paul Stewartf1961f82012-09-11 20:45:39 -0700368 for (int i = 1; i < GetFailureThreshold(); ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700369 ExpectTransmit(false);
Paul Stewart0443aa52012-08-09 10:43:50 -0700370 AdvanceTime(kTimeIncrement);
Paul Stewart6c72c972012-07-27 11:29:20 -0700371 TriggerRequestTimer();
372 EXPECT_FALSE(IsUnicast());
373 EXPECT_EQ(i, GetBroadcastFailureCount());
374 EXPECT_EQ(0, GetUnicastFailureCount());
375 EXPECT_EQ(GetTestPeriodMilliseconds(),
376 monitor_.GetResponseTimeMilliseconds());
377 }
378 ScopedMockLog log;
379 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
380 EXPECT_CALL(log,
381 Log(logging::LOG_ERROR, _,
382 HasSubstr("monitor has reached the failure threshold"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700383 EXPECT_CALL(metrics_, SendEnumToUMA(
384 HasSubstr("LinkMonitorFailure"),
385 Metrics::kLinkMonitorFailureThresholdReached, _));
Paul Stewart0443aa52012-08-09 10:43:50 -0700386 EXPECT_CALL(metrics_, SendToUMA(
387 HasSubstr("LinkMonitorSecondsToFailure"),
388 kTimeIncrement * GetFailureThreshold() / 1000, _, _, _));
389 EXPECT_CALL(metrics_, SendToUMA(
390 HasSubstr("BroadcastErrorsAtFailure"), GetFailureThreshold(), _, _, _));
391 EXPECT_CALL(metrics_, SendToUMA(
392 HasSubstr("UnicastErrorsAtFailure"), 0, _, _, _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700393 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
394 ExpectNoTransmit();
Paul Stewartf1961f82012-09-11 20:45:39 -0700395 EXPECT_CALL(monitor_, FailureCallbackHandler());
Paul Stewart0443aa52012-08-09 10:43:50 -0700396 AdvanceTime(kTimeIncrement);
Paul Stewart6c72c972012-07-27 11:29:20 -0700397 TriggerRequestTimer();
398 ExpectReset();
399}
400
401TEST_F(LinkMonitorTest, TimeoutUnicast) {
402 StartMonitor();
Paul Stewartff845fc2012-08-07 07:28:44 -0700403 // Successful broadcast receptions.
404 EXPECT_CALL(metrics_, SendToUMA(
405 HasSubstr("LinkMonitorResponseTimeSample"), 0, _, _, _))
406 .Times(GetFailureThreshold());
407 // Unsuccessful unicast receptions.
408 EXPECT_CALL(metrics_, SendToUMA(
409 HasSubstr("LinkMonitorResponseTimeSample"), GetTestPeriodMilliseconds(),
410 _, _, _)).Times(GetFailureThreshold());
Paul Stewart6c72c972012-07-27 11:29:20 -0700411 ReceiveCorrectResponse();
Paul Stewartf1961f82012-09-11 20:45:39 -0700412 for (int i = 1; i < GetFailureThreshold(); ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700413 // Failed unicast ARP.
414 ExpectTransmit(true);
415 TriggerRequestTimer();
416
417 // Successful broadcast ARP.
418 ExpectTransmit(false);
419 TriggerRequestTimer();
420 ReceiveCorrectResponse();
421
422 EXPECT_EQ(0, GetBroadcastFailureCount());
423 EXPECT_EQ(i, GetUnicastFailureCount());
424 }
425 // Last unicast ARP transmission.
426 ExpectTransmit(true);
427 TriggerRequestTimer();
428
429 ScopedMockLog log;
430 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
431 EXPECT_CALL(log,
432 Log(logging::LOG_ERROR, _,
433 HasSubstr("monitor has reached the failure threshold"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700434 EXPECT_CALL(metrics_, SendEnumToUMA(
435 HasSubstr("LinkMonitorFailure"),
436 Metrics::kLinkMonitorFailureThresholdReached, _));
Paul Stewart0443aa52012-08-09 10:43:50 -0700437 EXPECT_CALL(metrics_, SendToUMA(
438 HasSubstr("LinkMonitorSecondsToFailure"), 0, _, _, _));
439 EXPECT_CALL(metrics_, SendToUMA(
440 HasSubstr("BroadcastErrorsAtFailure"), 0, _, _, _));
441 EXPECT_CALL(metrics_, SendToUMA(
442 HasSubstr("UnicastErrorsAtFailure"), GetFailureThreshold(), _, _, _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700443 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
444 ExpectNoTransmit();
Paul Stewartf1961f82012-09-11 20:45:39 -0700445 EXPECT_CALL(monitor_, FailureCallbackHandler());
Paul Stewart6c72c972012-07-27 11:29:20 -0700446 TriggerRequestTimer();
447 ExpectReset();
448}
449
450TEST_F(LinkMonitorTest, Average) {
Paul Stewartf1961f82012-09-11 20:45:39 -0700451 const int kSamples[] = { 200, 950, 1200, 4096, 5000,
452 86, 120, 3060, 842, 750 };
453 const size_t filter_depth = GetMaxResponseSampleFilterDepth();
Paul Stewartff845fc2012-08-07 07:28:44 -0700454 EXPECT_CALL(metrics_, SendToUMA(
455 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _))
456 .Times(arraysize(kSamples));
Paul Stewart6c72c972012-07-27 11:29:20 -0700457 ASSERT_GT(arraysize(kSamples), filter_depth);
458 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700459 size_t i = 0;
460 int sum = 0;
Paul Stewart6c72c972012-07-27 11:29:20 -0700461 for (; i < filter_depth; ++i) {
462 AdvanceTime(kSamples[i]);
463 ReceiveCorrectResponse();
464 sum += kSamples[i];
465 EXPECT_EQ(sum / (i + 1), monitor_.GetResponseTimeMilliseconds());
466 SendNextRequest();
467 }
468 for (; i < arraysize(kSamples); ++i) {
469 AdvanceTime(kSamples[i]);
470 ReceiveCorrectResponse();
471 sum = (sum + kSamples[i]) * filter_depth / (filter_depth + 1);
472 EXPECT_EQ(sum / filter_depth, monitor_.GetResponseTimeMilliseconds());
473 SendNextRequest();
474 }
475}
476
477TEST_F(LinkMonitorTest, ImpulseResponse) {
Paul Stewartf1961f82012-09-11 20:45:39 -0700478 const int kNormalValue = 50;
479 const int kExceptionalValue = 5000;
480 const int filter_depth = GetMaxResponseSampleFilterDepth();
Paul Stewartff845fc2012-08-07 07:28:44 -0700481 EXPECT_CALL(metrics_, SendToUMA(
482 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _))
483 .Times(AnyNumber());
Paul Stewart6c72c972012-07-27 11:29:20 -0700484 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700485 for (int i = 0; i < filter_depth * 2; ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700486 AdvanceTime(kNormalValue);
487 ReceiveCorrectResponse();
488 EXPECT_EQ(kNormalValue, monitor_.GetResponseTimeMilliseconds());
489 SendNextRequest();
490 }
491 AdvanceTime(kExceptionalValue);
492 ReceiveCorrectResponse();
493 // Our expectation is that an impulse input will be a
494 // impulse_height / (filter_depth + 1) increase to the running average.
Paul Stewartf1961f82012-09-11 20:45:39 -0700495 int expected_impulse_response =
Paul Stewart6c72c972012-07-27 11:29:20 -0700496 kNormalValue + (kExceptionalValue - kNormalValue) / (filter_depth + 1);
497 EXPECT_EQ(expected_impulse_response, monitor_.GetResponseTimeMilliseconds());
498 SendNextRequest();
499
500 // From here, if we end up continuing to receive normal values, our
501 // running average should decay backwards to the normal value.
Paul Stewartf1961f82012-09-11 20:45:39 -0700502 const int failsafe = 100;
503 int last_value = monitor_.GetResponseTimeMilliseconds();
504 for (int i = 0; i < failsafe && last_value != kNormalValue; ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700505 AdvanceTime(kNormalValue);
506 ReceiveCorrectResponse();
507 // We should advance monotonically (but not necessarily linearly)
508 // back towards the normal value.
509 EXPECT_GE(last_value, monitor_.GetResponseTimeMilliseconds());
510 SendNextRequest();
511 last_value = monitor_.GetResponseTimeMilliseconds();
512 }
513 EXPECT_EQ(kNormalValue, last_value);
Paul Stewart3f43f432012-07-16 12:12:45 -0700514}
515
Paul Stewartf1961f82012-09-11 20:45:39 -0700516TEST_F(LinkMonitorTest, HardwareAddressToString) {
517 const uint8 address0[] = { 0, 1, 2, 3, 4, 5 };
518 EXPECT_EQ("00:01:02:03:04:05",
519 HardwareAddressToString(ByteString(address0, arraysize(address0))));
520 const uint8 address1[] = { 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd };
521 EXPECT_EQ("88:99:aa:bb:cc:dd",
522 HardwareAddressToString(ByteString(address1, arraysize(address1))));
523}
524
Paul Stewart3f43f432012-07-16 12:12:45 -0700525} // namespace shill