blob: f360fa0d79a9c289f36f83a79ca8bb4ca8351f21 [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()
Paul Stewart6c72c972012-07-27 11:29:20 -070081 : device_info_(
82 &control_,
83 reinterpret_cast<EventDispatcher*>(NULL),
84 reinterpret_cast<Metrics*>(NULL),
85 reinterpret_cast<Manager*>(NULL)),
Paul Stewart3f43f432012-07-16 12:12:45 -070086 connection_(new StrictMock<MockConnection>(&device_info_)),
Paul Stewartff845fc2012-08-07 07:28:44 -070087 monitor_(connection_, &dispatcher_, &metrics_, &device_info_),
Paul Stewart6c72c972012-07-27 11:29:20 -070088 client_(NULL),
89 next_client_(new StrictMock<MockArpClient>()),
90 gateway_ip_(IPAddress::kFamilyIPv4),
91 local_ip_(IPAddress::kFamilyIPv4),
92 gateway_mac_(kRemoteMACAddress, arraysize(kRemoteMACAddress)),
93 local_mac_(kLocalMACAddress, arraysize(kLocalMACAddress)),
94 zero_mac_(arraysize(kLocalMACAddress)),
95 link_scope_logging_was_enabled_(false) {}
Paul Stewart3f43f432012-07-16 12:12:45 -070096 virtual ~LinkMonitorTest() {}
97
Paul Stewart6c72c972012-07-27 11:29:20 -070098 virtual void SetUp() {
99 link_scope_logging_was_enabled_ = SLOG_IS_ON(Link, 0);
100 if (!link_scope_logging_was_enabled_) {
101 ScopeLogger::GetInstance()->EnableScopesByName("link");
102 ScopeLogger::GetInstance()->set_verbose_level(4);
103 }
104 monitor_.time_ = &time_;
Paul Stewart0443aa52012-08-09 10:43:50 -0700105 time_val_.tv_sec = 0;
106 time_val_.tv_usec = 0;
Paul Stewart6c72c972012-07-27 11:29:20 -0700107 EXPECT_CALL(time_, GetTimeMonotonic(_))
108 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
109 EXPECT_TRUE(local_ip_.SetAddressFromString(kLocalIPAddress));
110 EXPECT_CALL(*connection_, local()).WillRepeatedly(ReturnRef(local_ip_));
111 EXPECT_TRUE(gateway_ip_.SetAddressFromString(kRemoteIPAddress));
112 EXPECT_CALL(*connection_, gateway()).WillRepeatedly(ReturnRef(gateway_ip_));
113 }
114
115 virtual void TearDown() {
116 if (!link_scope_logging_was_enabled_) {
117 ScopeLogger::GetInstance()->EnableScopesByName("-link");
118 ScopeLogger::GetInstance()->set_verbose_level(0);
119 }
120 }
121
Paul Stewartf1961f82012-09-11 20:45:39 -0700122 void AdvanceTime(int time_ms) {
Han Shenfc349252012-08-30 11:36:04 -0700123 struct timeval adv_time = {
124 static_cast<time_t>(time_ms/1000),
125 static_cast<time_t>((time_ms % 1000) * 1000) };
Paul Stewart6c72c972012-07-27 11:29:20 -0700126 timeradd(&time_val_, &adv_time, &time_val_);
127 EXPECT_CALL(time_, GetTimeMonotonic(_))
128 .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
129 }
130
131 bool CreateMockClient() {
132 EXPECT_FALSE(monitor_.arp_client_.get());
133 if (client_) {
134 Mock::VerifyAndClearExpectations(client_);
135 }
136 client_ = next_client_;
137 next_client_ = new StrictMock<MockArpClient>();
138 monitor_.arp_client_.reset(client_);
139 return true;
140 }
Paul Stewart3f43f432012-07-16 12:12:45 -0700141
Paul Stewartf1961f82012-09-11 20:45:39 -0700142 string HardwareAddressToString(const ByteString &address) {
143 return LinkMonitor::HardwareAddressToString(address);
144 }
145
Paul Stewart3f43f432012-07-16 12:12:45 -0700146 protected:
Paul Stewart6c72c972012-07-27 11:29:20 -0700147 void ExpectReset() {
148 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
149 EXPECT_FALSE(GetArpClient());
150 EXPECT_TRUE(GetSendRequestCallback().IsCancelled());
151 EXPECT_EQ(0, GetBroadcastFailureCount());
152 EXPECT_EQ(0, GetUnicastFailureCount());
153 EXPECT_FALSE(IsUnicast());
154 }
155 const ArpClient *GetArpClient() { return monitor_.arp_client_.get(); }
156 void TriggerRequestTimer() {
157 GetSendRequestCallback().callback().Run();
158 }
159 const base::CancelableClosure &GetSendRequestCallback() {
160 return monitor_.send_request_callback_;
161 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700162 int GetBroadcastFailureCount() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700163 return monitor_.broadcast_failure_count_;
164 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700165 int GetUnicastFailureCount() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700166 return monitor_.unicast_failure_count_;
167 }
168 bool IsUnicast() { return monitor_.is_unicast_; }
Paul Stewartf1961f82012-09-11 20:45:39 -0700169 int GetTestPeriodMilliseconds() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700170 return LinkMonitor::kTestPeriodMilliseconds;
171 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700172 int GetFailureThreshold() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700173 return LinkMonitor::kFailureThreshold;
174 }
Paul Stewartf1961f82012-09-11 20:45:39 -0700175 int GetMaxResponseSampleFilterDepth() {
Paul Stewart6c72c972012-07-27 11:29:20 -0700176 return LinkMonitor::kMaxResponseSampleFilterDepth;
177 }
178 void ExpectTransmit(bool is_unicast) {
179 const ByteString &destination_mac = is_unicast ? gateway_mac_ : zero_mac_;
180 if (monitor_.arp_client_.get()) {
181 EXPECT_EQ(client_, monitor_.arp_client_.get());
182 EXPECT_CALL(*client_, TransmitRequest(
183 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
184 .WillOnce(Return(true));
185 } else {
186 EXPECT_CALL(monitor_, CreateClient())
187 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
188 EXPECT_CALL(*next_client_, TransmitRequest(
189 IsArpRequest(local_ip_, gateway_ip_, local_mac_, destination_mac)))
190 .WillOnce(Return(true));
191 }
192 EXPECT_CALL(dispatcher_, PostDelayedTask(_, GetTestPeriodMilliseconds()));
193 }
194 void SendNextRequest() {
195 EXPECT_CALL(monitor_, CreateClient())
196 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
197 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(true));
198 EXPECT_CALL(dispatcher_, PostDelayedTask(_, GetTestPeriodMilliseconds()));
199 TriggerRequestTimer();
200 }
201 void ExpectNoTransmit() {
202 MockArpClient *client =
203 monitor_.arp_client_.get() ? client_ : next_client_;
204 EXPECT_CALL(*client, TransmitRequest(_)).Times(0);
205 }
206 void StartMonitor() {
207 EXPECT_CALL(device_info_, GetMACAddress(0, _))
208 .WillOnce(DoAll(SetArgumentPointee<1>(local_mac_), Return(true)));
209 ExpectTransmit(false);
210 EXPECT_TRUE(monitor_.Start());
211 EXPECT_TRUE(GetArpClient());
212 EXPECT_FALSE(IsUnicast());
213 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
214 }
215 bool SimulateReceiveReply(ArpPacket *packet, ByteString *sender) {
216 packet->set_local_ip_address(rx_packet_.local_ip_address());
217 packet->set_remote_ip_address(rx_packet_.remote_ip_address());
218 packet->set_local_mac_address(rx_packet_.local_mac_address());
219 packet->set_remote_mac_address(rx_packet_.remote_mac_address());
220 return true;
221 }
222 void ReceiveResponse(const IPAddress &local_ip,
223 const ByteString &local_mac,
224 const IPAddress &remote_ip,
225 const ByteString &remote_mac) {
226 rx_packet_.set_local_ip_address(local_ip);
227 rx_packet_.set_local_mac_address(local_mac);
228 rx_packet_.set_remote_ip_address(remote_ip);
229 rx_packet_.set_remote_mac_address(remote_mac);
230
231 EXPECT_CALL(*client_, ReceiveReply(_, _))
232 .WillOnce(Invoke(this, &LinkMonitorTest::SimulateReceiveReply));
233 monitor_.ReceiveResponse(0);
234 }
235 void ReceiveCorrectResponse() {
Paul Stewart9f7823e2012-08-09 10:58:26 -0700236 ReceiveResponse(gateway_ip_, gateway_mac_, local_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700237 }
238
239 MockEventDispatcher dispatcher_;
Paul Stewartff845fc2012-08-07 07:28:44 -0700240 StrictMock<MockMetrics> metrics_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700241 MockControl control_;
242 NiceMock<MockDeviceInfo> device_info_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700243 scoped_refptr<MockConnection> connection_;
Paul Stewart6c72c972012-07-27 11:29:20 -0700244 StrictMock<LinkMonitorForTest> monitor_;
245 MockTime time_;
246 struct timeval time_val_;
247 // This is owned by the LinkMonitor, and only tracked here for EXPECT*().
248 MockArpClient *client_;
249 // This is owned by the test until it is handed to the LinkMonitorForTest
250 // and placed // in client_ above.
251 MockArpClient *next_client_;
252 IPAddress gateway_ip_;
253 IPAddress local_ip_;
254 ByteString gateway_mac_;
255 ByteString local_mac_;
256 ByteString zero_mac_;
257 ArpPacket rx_packet_;
258 bool link_scope_logging_was_enabled_;
Paul Stewart3f43f432012-07-16 12:12:45 -0700259};
260
Paul Stewart6c72c972012-07-27 11:29:20 -0700261
Paul Stewart3f43f432012-07-16 12:12:45 -0700262TEST_F(LinkMonitorTest, Constructor) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700263 ExpectReset();
264}
265
266TEST_F(LinkMonitorTest, StartFailedGetMACAddress) {
267 ScopedMockLog log;
268 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
269 EXPECT_CALL(log,
270 Log(logging::LOG_ERROR, _,
271 HasSubstr("Could not get local MAC address"))).Times(1);
272 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(false));
Paul Stewartff845fc2012-08-07 07:28:44 -0700273 EXPECT_CALL(metrics_, SendEnumToUMA(
274 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorMacAddressNotFound,
275 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700276 EXPECT_CALL(monitor_, CreateClient()).Times(0);
277 EXPECT_FALSE(monitor_.Start());
278 ExpectReset();
279}
280
281TEST_F(LinkMonitorTest, StartFailedCreateClient) {
282 ScopedMockLog log;
283 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
284 EXPECT_CALL(log,
285 Log(logging::LOG_ERROR, _,
286 HasSubstr("Failed to start ARP client"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700287 EXPECT_CALL(metrics_, SendEnumToUMA(
288 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorClientStartFailure,
289 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700290 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
291 EXPECT_CALL(monitor_, CreateClient()).WillOnce(Return(false));
292 EXPECT_FALSE(monitor_.Start());
293 ExpectReset();
294}
295
296TEST_F(LinkMonitorTest, StartFailedTransmitRequest) {
297 ScopedMockLog log;
298 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
299 EXPECT_CALL(log,
300 Log(logging::LOG_ERROR, _,
301 HasSubstr("Failed to send ARP"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700302 EXPECT_CALL(metrics_, SendEnumToUMA(
303 HasSubstr("LinkMonitorFailure"), Metrics::kLinkMonitorTransmitFailure,
304 _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700305 EXPECT_CALL(device_info_, GetMACAddress(0, _)).WillOnce(Return(true));
306 EXPECT_CALL(monitor_, CreateClient())
307 .WillOnce(Invoke(this, &LinkMonitorTest::CreateMockClient));
308 EXPECT_CALL(*next_client_, TransmitRequest(_)).WillOnce(Return(false));
309 EXPECT_FALSE(monitor_.Start());
310 ExpectReset();
311}
312
313TEST_F(LinkMonitorTest, StartSuccess) {
314 StartMonitor();
315}
316
317TEST_F(LinkMonitorTest, Stop) {
318 StartMonitor();
319 monitor_.Stop();
320 ExpectReset();
321}
322
323TEST_F(LinkMonitorTest, ReplyReception) {
324 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700325 const int kResponseTime = 1234;
Paul Stewart6c72c972012-07-27 11:29:20 -0700326 AdvanceTime(kResponseTime);
327 ScopedMockLog log;
328
329 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
330 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our IP"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700331 ReceiveResponse(gateway_ip_, gateway_mac_, gateway_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700332 Mock::VerifyAndClearExpectations(&log);
333
334 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
335 EXPECT_CALL(log, Log(_, _, HasSubstr("not for our MAC"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700336 ReceiveResponse(gateway_ip_, gateway_mac_, local_ip_, gateway_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700337 Mock::VerifyAndClearExpectations(&log);
338
339 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
340 EXPECT_CALL(log, Log(_, _, HasSubstr("not from the gateway"))).Times(1);
Paul Stewart9f7823e2012-08-09 10:58:26 -0700341 ReceiveResponse(local_ip_, gateway_mac_, local_ip_, local_mac_);
Paul Stewart6c72c972012-07-27 11:29:20 -0700342 Mock::VerifyAndClearExpectations(&log);
343
344 EXPECT_TRUE(GetArpClient());
345 EXPECT_FALSE(monitor_.GetResponseTimeMilliseconds());
346 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
347 EXPECT_CALL(log, Log(_, _, HasSubstr("Found gateway"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700348 EXPECT_CALL(metrics_, SendToUMA(
349 HasSubstr("LinkMonitorResponseTimeSample"), kResponseTime,
350 _, _, _)).Times(1);
Paul Stewart6c72c972012-07-27 11:29:20 -0700351 ReceiveCorrectResponse();
352 EXPECT_FALSE(GetArpClient());
353 EXPECT_EQ(kResponseTime, monitor_.GetResponseTimeMilliseconds());
354 EXPECT_TRUE(IsUnicast());
355}
356
357TEST_F(LinkMonitorTest, TimeoutBroadcast) {
Paul Stewartff845fc2012-08-07 07:28:44 -0700358 EXPECT_CALL(metrics_, SendToUMA(
359 HasSubstr("LinkMonitorResponseTimeSample"), GetTestPeriodMilliseconds(),
360 _, _, _)).Times(GetFailureThreshold());
Paul Stewart6c72c972012-07-27 11:29:20 -0700361 StartMonitor();
Paul Stewart0443aa52012-08-09 10:43:50 -0700362 // This value doesn't match real life (the timer in this scenario should
363 // advance by LinkMonitor::kTestPeriodMilliseconds), but this demonstrates
364 // the LinkMonitorSecondsToFailure independent from the response-time
365 // figures.
366 const int kTimeIncrement = 1000;
Paul Stewartf1961f82012-09-11 20:45:39 -0700367 for (int i = 1; i < GetFailureThreshold(); ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700368 ExpectTransmit(false);
Paul Stewart0443aa52012-08-09 10:43:50 -0700369 AdvanceTime(kTimeIncrement);
Paul Stewart6c72c972012-07-27 11:29:20 -0700370 TriggerRequestTimer();
371 EXPECT_FALSE(IsUnicast());
372 EXPECT_EQ(i, GetBroadcastFailureCount());
373 EXPECT_EQ(0, GetUnicastFailureCount());
374 EXPECT_EQ(GetTestPeriodMilliseconds(),
375 monitor_.GetResponseTimeMilliseconds());
376 }
377 ScopedMockLog log;
378 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
379 EXPECT_CALL(log,
380 Log(logging::LOG_ERROR, _,
381 HasSubstr("monitor has reached the failure threshold"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700382 EXPECT_CALL(metrics_, SendEnumToUMA(
383 HasSubstr("LinkMonitorFailure"),
384 Metrics::kLinkMonitorFailureThresholdReached, _));
Paul Stewart0443aa52012-08-09 10:43:50 -0700385 EXPECT_CALL(metrics_, SendToUMA(
386 HasSubstr("LinkMonitorSecondsToFailure"),
387 kTimeIncrement * GetFailureThreshold() / 1000, _, _, _));
388 EXPECT_CALL(metrics_, SendToUMA(
389 HasSubstr("BroadcastErrorsAtFailure"), GetFailureThreshold(), _, _, _));
390 EXPECT_CALL(metrics_, SendToUMA(
391 HasSubstr("UnicastErrorsAtFailure"), 0, _, _, _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700392 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
393 ExpectNoTransmit();
Paul Stewartf1961f82012-09-11 20:45:39 -0700394 EXPECT_CALL(monitor_, FailureCallbackHandler());
Paul Stewart0443aa52012-08-09 10:43:50 -0700395 AdvanceTime(kTimeIncrement);
Paul Stewart6c72c972012-07-27 11:29:20 -0700396 TriggerRequestTimer();
397 ExpectReset();
398}
399
400TEST_F(LinkMonitorTest, TimeoutUnicast) {
401 StartMonitor();
Paul Stewartff845fc2012-08-07 07:28:44 -0700402 // Successful broadcast receptions.
403 EXPECT_CALL(metrics_, SendToUMA(
404 HasSubstr("LinkMonitorResponseTimeSample"), 0, _, _, _))
405 .Times(GetFailureThreshold());
406 // Unsuccessful unicast receptions.
407 EXPECT_CALL(metrics_, SendToUMA(
408 HasSubstr("LinkMonitorResponseTimeSample"), GetTestPeriodMilliseconds(),
409 _, _, _)).Times(GetFailureThreshold());
Paul Stewart6c72c972012-07-27 11:29:20 -0700410 ReceiveCorrectResponse();
Paul Stewartf1961f82012-09-11 20:45:39 -0700411 for (int i = 1; i < GetFailureThreshold(); ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700412 // Failed unicast ARP.
413 ExpectTransmit(true);
414 TriggerRequestTimer();
415
416 // Successful broadcast ARP.
417 ExpectTransmit(false);
418 TriggerRequestTimer();
419 ReceiveCorrectResponse();
420
421 EXPECT_EQ(0, GetBroadcastFailureCount());
422 EXPECT_EQ(i, GetUnicastFailureCount());
423 }
424 // Last unicast ARP transmission.
425 ExpectTransmit(true);
426 TriggerRequestTimer();
427
428 ScopedMockLog log;
429 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
430 EXPECT_CALL(log,
431 Log(logging::LOG_ERROR, _,
432 HasSubstr("monitor has reached the failure threshold"))).Times(1);
Paul Stewartff845fc2012-08-07 07:28:44 -0700433 EXPECT_CALL(metrics_, SendEnumToUMA(
434 HasSubstr("LinkMonitorFailure"),
435 Metrics::kLinkMonitorFailureThresholdReached, _));
Paul Stewart0443aa52012-08-09 10:43:50 -0700436 EXPECT_CALL(metrics_, SendToUMA(
437 HasSubstr("LinkMonitorSecondsToFailure"), 0, _, _, _));
438 EXPECT_CALL(metrics_, SendToUMA(
439 HasSubstr("BroadcastErrorsAtFailure"), 0, _, _, _));
440 EXPECT_CALL(metrics_, SendToUMA(
441 HasSubstr("UnicastErrorsAtFailure"), GetFailureThreshold(), _, _, _));
Paul Stewart6c72c972012-07-27 11:29:20 -0700442 EXPECT_FALSE(GetSendRequestCallback().IsCancelled());
443 ExpectNoTransmit();
Paul Stewartf1961f82012-09-11 20:45:39 -0700444 EXPECT_CALL(monitor_, FailureCallbackHandler());
Paul Stewart6c72c972012-07-27 11:29:20 -0700445 TriggerRequestTimer();
446 ExpectReset();
447}
448
449TEST_F(LinkMonitorTest, Average) {
Paul Stewartf1961f82012-09-11 20:45:39 -0700450 const int kSamples[] = { 200, 950, 1200, 4096, 5000,
451 86, 120, 3060, 842, 750 };
452 const size_t filter_depth = GetMaxResponseSampleFilterDepth();
Paul Stewartff845fc2012-08-07 07:28:44 -0700453 EXPECT_CALL(metrics_, SendToUMA(
454 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _))
455 .Times(arraysize(kSamples));
Paul Stewart6c72c972012-07-27 11:29:20 -0700456 ASSERT_GT(arraysize(kSamples), filter_depth);
457 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700458 size_t i = 0;
459 int sum = 0;
Paul Stewart6c72c972012-07-27 11:29:20 -0700460 for (; i < filter_depth; ++i) {
461 AdvanceTime(kSamples[i]);
462 ReceiveCorrectResponse();
463 sum += kSamples[i];
464 EXPECT_EQ(sum / (i + 1), monitor_.GetResponseTimeMilliseconds());
465 SendNextRequest();
466 }
467 for (; i < arraysize(kSamples); ++i) {
468 AdvanceTime(kSamples[i]);
469 ReceiveCorrectResponse();
470 sum = (sum + kSamples[i]) * filter_depth / (filter_depth + 1);
471 EXPECT_EQ(sum / filter_depth, monitor_.GetResponseTimeMilliseconds());
472 SendNextRequest();
473 }
474}
475
476TEST_F(LinkMonitorTest, ImpulseResponse) {
Paul Stewartf1961f82012-09-11 20:45:39 -0700477 const int kNormalValue = 50;
478 const int kExceptionalValue = 5000;
479 const int filter_depth = GetMaxResponseSampleFilterDepth();
Paul Stewartff845fc2012-08-07 07:28:44 -0700480 EXPECT_CALL(metrics_, SendToUMA(
481 HasSubstr("LinkMonitorResponseTimeSample"), _, _, _, _))
482 .Times(AnyNumber());
Paul Stewart6c72c972012-07-27 11:29:20 -0700483 StartMonitor();
Paul Stewartf1961f82012-09-11 20:45:39 -0700484 for (int i = 0; i < filter_depth * 2; ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700485 AdvanceTime(kNormalValue);
486 ReceiveCorrectResponse();
487 EXPECT_EQ(kNormalValue, monitor_.GetResponseTimeMilliseconds());
488 SendNextRequest();
489 }
490 AdvanceTime(kExceptionalValue);
491 ReceiveCorrectResponse();
492 // Our expectation is that an impulse input will be a
493 // impulse_height / (filter_depth + 1) increase to the running average.
Paul Stewartf1961f82012-09-11 20:45:39 -0700494 int expected_impulse_response =
Paul Stewart6c72c972012-07-27 11:29:20 -0700495 kNormalValue + (kExceptionalValue - kNormalValue) / (filter_depth + 1);
496 EXPECT_EQ(expected_impulse_response, monitor_.GetResponseTimeMilliseconds());
497 SendNextRequest();
498
499 // From here, if we end up continuing to receive normal values, our
500 // running average should decay backwards to the normal value.
Paul Stewartf1961f82012-09-11 20:45:39 -0700501 const int failsafe = 100;
502 int last_value = monitor_.GetResponseTimeMilliseconds();
503 for (int i = 0; i < failsafe && last_value != kNormalValue; ++i) {
Paul Stewart6c72c972012-07-27 11:29:20 -0700504 AdvanceTime(kNormalValue);
505 ReceiveCorrectResponse();
506 // We should advance monotonically (but not necessarily linearly)
507 // back towards the normal value.
508 EXPECT_GE(last_value, monitor_.GetResponseTimeMilliseconds());
509 SendNextRequest();
510 last_value = monitor_.GetResponseTimeMilliseconds();
511 }
512 EXPECT_EQ(kNormalValue, last_value);
Paul Stewart3f43f432012-07-16 12:12:45 -0700513}
514
Paul Stewartf1961f82012-09-11 20:45:39 -0700515TEST_F(LinkMonitorTest, HardwareAddressToString) {
516 const uint8 address0[] = { 0, 1, 2, 3, 4, 5 };
517 EXPECT_EQ("00:01:02:03:04:05",
518 HardwareAddressToString(ByteString(address0, arraysize(address0))));
519 const uint8 address1[] = { 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd };
520 EXPECT_EQ("88:99:aa:bb:cc:dd",
521 HardwareAddressToString(ByteString(address1, arraysize(address1))));
522}
523
Paul Stewart3f43f432012-07-16 12:12:45 -0700524} // namespace shill