blob: a7de2155fa4700dd30895dc73bda768ca5f11fab [file] [log] [blame]
Samuel Tanf66080e2015-06-18 15:53:00 -07001// Copyright 2015 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/icmp_session.h"
6
7#include <base/test/simple_test_tick_clock.h>
8#include <gtest/gtest.h>
9
10#include "shill/mock_event_dispatcher.h"
11#include "shill/mock_icmp.h"
12#include "shill/net/ip_address.h"
13
14using base::Bind;
15using base::Unretained;
16using testing::_;
17using testing::NiceMock;
18using testing::Return;
19using testing::StrictMock;
20using testing::Test;
21
22namespace shill {
23
24namespace {
25
Samuel Tanc3227bb2015-08-28 16:40:07 -070026// Note: this header is given in network byte order, since
27// IcmpSession::OnEchoReplyReceived expects to receive a raw IP packet.
28const uint8_t kIpHeader[] = {0x45, 0x80, 0x00, 0x1c, 0x63, 0xd3, 0x00,
29 0x00, 0x39, 0x01, 0xcc, 0x9f, 0x4a, 0x7d,
30 0xe0, 0x18, 0x64, 0x6e, 0xc1, 0xea};
Samuel Tanf66080e2015-06-18 15:53:00 -070031// ICMP echo replies with 0 bytes of data and and echo ID 0. Sequence numbers
32// are 0x8, 0x9, and 0xa respectively to simulate replies to a sequence of sent
33// echo requests.
34const uint8_t kIcmpEchoReply1[] = {0x00, 0x00, 0xf7, 0xff,
35 0x00, 0x00, 0x08, 0x00};
36const uint16_t kIcmpEchoReply1_SeqNum = 0x08;
37const uint8_t kIcmpEchoReply2[] = {0x00, 0x00, 0xf6, 0xff,
38 0x00, 0x00, 0x09, 0x00};
39const uint16_t kIcmpEchoReply2_SeqNum = 0x09;
40const uint8_t kIcmpEchoReply3[] = {0x00, 0x00, 0xf5, 0xff,
41 0x00, 0x00, 0x0a, 0x00};
42const uint16_t kIcmpEchoReply3_SeqNum = 0x0a;
43
44// This ICMP echo reply has an echo ID of 0xe, which is different from the
45// echo ID used in the unit tests (0).
46const uint8_t kIcmpEchoReplyDifferentEchoID[] = {0x00, 0x00, 0xea, 0xff,
47 0x0e, 0x00, 0x0b, 0x00};
48
49} // namespace
50
51MATCHER_P(IsIPAddress, address, "") {
52 // IPAddress objects don't support the "==" operator as per style, so we need
53 // a custom matcher.
54 return address.Equals(arg);
55}
56
57class IcmpSessionTest : public Test {
58 public:
59 IcmpSessionTest() : icmp_session_(&dispatcher_) {}
60 virtual ~IcmpSessionTest() {}
61
62 virtual void SetUp() {
63 icmp_session_.tick_clock_ = &testing_clock_;
64 icmp_ = new NiceMock<MockIcmp>();
65 // Passes ownership.
66 icmp_session_.icmp_.reset(icmp_);
67 ON_CALL(*icmp_, IsStarted()).WillByDefault(Return(false));
68 }
69
70 virtual void TearDown() {
71 EXPECT_CALL(*icmp_, IsStarted());
72 IcmpSession::kNextUniqueEchoId = 0;
73 }
74
75 MOCK_METHOD1(ResultCallback, void(const IcmpSession::IcmpSessionResult&));
76
77 protected:
78 static const char kIPAddress[];
79
80 void StartAndVerify(const IPAddress& destination) {
81 EXPECT_CALL(*icmp_, IsStarted());
82 EXPECT_CALL(*icmp_, Start()).WillOnce(Return(true));
83 EXPECT_CALL(dispatcher_, CreateInputHandler(icmp_->socket(), _, _));
84 EXPECT_CALL(dispatcher_, PostDelayedTask(_, GetTimeoutSeconds() * 1000));
85 EXPECT_CALL(dispatcher_, PostTask(_));
86 EXPECT_TRUE(Start(destination));
87 EXPECT_TRUE(GetSeqNumToSentRecvTime()->empty());
88 EXPECT_TRUE(GetReceivedEchoReplySeqNumbers()->empty());
89 EXPECT_CALL(*icmp_, IsStarted()).WillRepeatedly(Return(true));
90 }
91
92 bool Start(const IPAddress& destination) {
93 return icmp_session_.Start(
94 destination, Bind(&IcmpSessionTest::ResultCallback, Unretained(this)));
95 }
96
97 void Stop() {
98 icmp_session_.Stop();
99 }
100
101 bool SeqNumToSentRecvTimeContains(uint16_t seq_num) {
102 return icmp_session_.seq_num_to_sent_recv_time_.find(seq_num) !=
103 icmp_session_.seq_num_to_sent_recv_time_.end();
104 }
105
106 bool ReceivedEchoReplySeqNumbersContains(uint16_t seq_num) {
107 return icmp_session_.received_echo_reply_seq_numbers_.find(seq_num) !=
108 icmp_session_.received_echo_reply_seq_numbers_.end();
109 }
110
111 void TransmitEchoRequestTask(const IPAddress& destination,
112 bool transmit_request_success) {
113 EXPECT_CALL(*icmp_, TransmitEchoRequest(IsIPAddress(destination),
114 icmp_session_.echo_id_,
115 GetCurrentSequenceNumber()))
116 .WillOnce(Return(transmit_request_success));
117 icmp_session_.TransmitEchoRequestTask(destination);
118 }
119
Samuel Tan42c33a42015-07-14 17:52:57 -0700120 void ReportResultAndStopSession() {
121 icmp_session_.ReportResultAndStopSession();
122 }
123
Samuel Tanf66080e2015-06-18 15:53:00 -0700124 void VerifyIcmpSessionStopped() {
125 EXPECT_TRUE(icmp_session_.timeout_callback_.IsCancelled());
Samuel Tanf66080e2015-06-18 15:53:00 -0700126 EXPECT_FALSE(icmp_session_.echo_reply_handler_);
127 }
128
129 void OnEchoReplyReceived(InputData* data) {
130 icmp_session_.OnEchoReplyReceived(data);
131 }
132
133 IcmpSession::IcmpSessionResult GenerateIcmpResult() {
134 return icmp_session_.GenerateIcmpResult();
135 }
136
137 std::map<uint16_t, IcmpSession::SentRecvTimePair>* GetSeqNumToSentRecvTime() {
138 return &icmp_session_.seq_num_to_sent_recv_time_;
139 }
140 std::set<uint16_t>* GetReceivedEchoReplySeqNumbers() {
141 return &icmp_session_.received_echo_reply_seq_numbers_;
142 }
143 uint16_t GetNextUniqueEchoId() const {
144 return IcmpSession::kNextUniqueEchoId;
145 }
146 int GetTotalNumEchoRequests() const {
147 return IcmpSession::kTotalNumEchoRequests;
148 }
149 int GetCurrentSequenceNumber() const {
150 return icmp_session_.current_sequence_number_;
151 }
152 void SetCurrentSequenceNumber(uint16_t val) {
153 icmp_session_.current_sequence_number_ = val;
154 }
155 size_t GetTimeoutSeconds() const { return IcmpSession::kTimeoutSeconds; }
156 int GetEchoRequestIntervalSeconds() const {
157 return IcmpSession::kEchoRequestIntervalSeconds;
158 }
159
160 MockIcmp* icmp_;
161 StrictMock<MockEventDispatcher> dispatcher_;
162 IcmpSession icmp_session_;
163 base::SimpleTestTickClock testing_clock_;
164};
165
166const char IcmpSessionTest::kIPAddress[] = "10.0.1.1";
167
168TEST_F(IcmpSessionTest, Constructor) {
169 // |icmp_session_| should have been assigned the value of |kNextUniqueEchoId|
170 // on construction, and caused the value of this static variable to be
171 // incremented.
172 uint16_t saved_echo_id = GetNextUniqueEchoId();
173 EXPECT_EQ(saved_echo_id - 1, icmp_session_.echo_id_);
174
175 // The next IcmpSession object constructed, |session| should get the next
176 // unique value of |kNextUniqueEchoId|, and further increment this variable.
177 IcmpSession session(&dispatcher_);
178 EXPECT_EQ(saved_echo_id, session.echo_id_);
179 EXPECT_EQ(saved_echo_id + 1, GetNextUniqueEchoId());
180}
181
182TEST_F(IcmpSessionTest, StartWhileAlreadyStarted) {
183 IPAddress ipv4_destination(IPAddress::kFamilyIPv4);
184 EXPECT_TRUE(ipv4_destination.SetAddressFromString(kIPAddress));
185 StartAndVerify(ipv4_destination);
186
187 // Since an ICMP session is already started, we should fail to start it again.
188 EXPECT_CALL(*icmp_, Start()).Times(0);
189 EXPECT_CALL(dispatcher_, CreateInputHandler(_, _, _)).Times(0);
190 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
191 EXPECT_CALL(dispatcher_, PostTask(_)).Times(0);
192 EXPECT_FALSE(Start(ipv4_destination));
193}
194
195TEST_F(IcmpSessionTest, StopWhileNotStarted) {
196 // Attempting to stop the ICMP session while it is not started should do
197 // nothing.
198 EXPECT_CALL(*icmp_, IsStarted()).WillOnce(Return(false));
199 EXPECT_CALL(*this, ResultCallback(_)).Times(0);
200 EXPECT_CALL(*icmp_, Stop()).Times(0);
201 Stop();
202}
203
204TEST_F(IcmpSessionTest, SessionSuccess) {
205 // Test a successful ICMP session where the sending of requests and receiving
206 // of replies are interleaved. Moreover, test the case where transmitting an
207 // echo request fails.
208
209 base::TimeTicks now = testing_clock_.NowTicks();
210 base::TimeTicks kSentTime1 = base::TimeTicks::FromInternalValue(10);
211 base::TimeTicks kRecvTime1 = base::TimeTicks::FromInternalValue(20);
212 base::TimeTicks kSentTime2 = base::TimeTicks::FromInternalValue(30);
213 base::TimeTicks kSentTime3 = base::TimeTicks::FromInternalValue(40);
214 base::TimeTicks kRecvTime2 = base::TimeTicks::FromInternalValue(50);
215 base::TimeTicks kWrongEchoIDRecvTime = base::TimeTicks::FromInternalValue(60);
216 base::TimeTicks kRecvTime3 = base::TimeTicks::FromInternalValue(70);
217
218 IcmpSession::IcmpSessionResult expected_result;
219 expected_result.push_back(kRecvTime1 - kSentTime1);
220 expected_result.push_back(kRecvTime2 - kSentTime2);
221 expected_result.push_back(kRecvTime3 - kSentTime3);
222
223 // Initiate session.
224 IPAddress ipv4_destination(IPAddress::kFamilyIPv4);
225 EXPECT_TRUE(ipv4_destination.SetAddressFromString(kIPAddress));
226 StartAndVerify(ipv4_destination);
227
228 // Send the first echo request.
229 testing_clock_.Advance(kSentTime1 - now);
230 now = testing_clock_.NowTicks();
231 SetCurrentSequenceNumber(kIcmpEchoReply1_SeqNum);
232 EXPECT_CALL(dispatcher_,
233 PostDelayedTask(_, GetEchoRequestIntervalSeconds() * 1000));
234 TransmitEchoRequestTask(ipv4_destination, true);
235 EXPECT_TRUE(GetReceivedEchoReplySeqNumbers()->empty());
236 EXPECT_EQ(1, GetSeqNumToSentRecvTime()->size());
237 EXPECT_TRUE(SeqNumToSentRecvTimeContains(kIcmpEchoReply1_SeqNum));
238 EXPECT_EQ(now, GetSeqNumToSentRecvTime()->at(kIcmpEchoReply1_SeqNum).first);
239 EXPECT_EQ(kIcmpEchoReply2_SeqNum, GetCurrentSequenceNumber());
240
241 // Receive first reply.
242 testing_clock_.Advance(kRecvTime1 - now);
243 now = testing_clock_.NowTicks();
Samuel Tanc3227bb2015-08-28 16:40:07 -0700244 uint8_t buffer_1[sizeof(kIpHeader) + sizeof(kIcmpEchoReply1)];
245 memcpy(buffer_1, kIpHeader, sizeof(kIpHeader));
246 memcpy(buffer_1 + sizeof(kIpHeader), kIcmpEchoReply1,
247 sizeof(kIcmpEchoReply1));
Samuel Tanf66080e2015-06-18 15:53:00 -0700248 InputData data_1(reinterpret_cast<unsigned char*>(buffer_1),
249 sizeof(buffer_1));
250 EXPECT_CALL(*this, ResultCallback(_)).Times(0);
251 OnEchoReplyReceived(&data_1);
252 EXPECT_EQ(1, GetReceivedEchoReplySeqNumbers()->size());
253 EXPECT_TRUE(ReceivedEchoReplySeqNumbersContains(kIcmpEchoReply1_SeqNum));
254
255 // Send the second echo request.
256 testing_clock_.Advance(kSentTime2 - now);
257 now = testing_clock_.NowTicks();
258 EXPECT_CALL(dispatcher_,
259 PostDelayedTask(_, GetEchoRequestIntervalSeconds() * 1000));
260 TransmitEchoRequestTask(ipv4_destination, true);
261 EXPECT_EQ(1, GetReceivedEchoReplySeqNumbers()->size());
262 EXPECT_EQ(2, GetSeqNumToSentRecvTime()->size());
263 EXPECT_TRUE(SeqNumToSentRecvTimeContains(kIcmpEchoReply2_SeqNum));
264 EXPECT_EQ(now, GetSeqNumToSentRecvTime()->at(kIcmpEchoReply2_SeqNum).first);
265 EXPECT_EQ(kIcmpEchoReply3_SeqNum, GetCurrentSequenceNumber());
266
267 // Sending final request.
268 testing_clock_.Advance(kSentTime3 - now);
269 now = testing_clock_.NowTicks();
270 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
271 EXPECT_CALL(*icmp_, Stop()).Times(0);
272 TransmitEchoRequestTask(ipv4_destination, true);
273 EXPECT_EQ(1, GetReceivedEchoReplySeqNumbers()->size());
274 EXPECT_EQ(3, GetSeqNumToSentRecvTime()->size());
275 EXPECT_TRUE(SeqNumToSentRecvTimeContains(kIcmpEchoReply3_SeqNum));
276 EXPECT_EQ(now, GetSeqNumToSentRecvTime()->at(kIcmpEchoReply3_SeqNum).first);
277 EXPECT_EQ(kIcmpEchoReply3_SeqNum + 1, GetCurrentSequenceNumber());
278
279 // Receive second reply.
280 testing_clock_.Advance(kRecvTime2 - now);
281 now = testing_clock_.NowTicks();
Samuel Tanc3227bb2015-08-28 16:40:07 -0700282 uint8_t buffer_2[sizeof(kIpHeader) + sizeof(kIcmpEchoReply2)];
283 memcpy(buffer_2, kIpHeader, sizeof(kIpHeader));
284 memcpy(buffer_2 + sizeof(kIpHeader), kIcmpEchoReply2,
285 sizeof(kIcmpEchoReply2));
Samuel Tanf66080e2015-06-18 15:53:00 -0700286 InputData data_2(reinterpret_cast<unsigned char*>(buffer_2),
287 sizeof(buffer_2));
288 EXPECT_CALL(*this, ResultCallback(_)).Times(0);
289 EXPECT_CALL(*icmp_, Stop()).Times(0);
290 OnEchoReplyReceived(&data_2);
291 EXPECT_EQ(3, GetSeqNumToSentRecvTime()->size());
292 EXPECT_EQ(2, GetReceivedEchoReplySeqNumbers()->size());
293 EXPECT_TRUE(ReceivedEchoReplySeqNumbersContains(kIcmpEchoReply2_SeqNum));
294
295 // Receive a reply that has an echo ID that does not match that of this
296 // ICMP session. This reply will not be processed.
297 testing_clock_.Advance(kWrongEchoIDRecvTime - now);
298 now = testing_clock_.NowTicks();
Samuel Tanc3227bb2015-08-28 16:40:07 -0700299 uint8_t buffer_3[sizeof(kIpHeader) + sizeof(kIcmpEchoReplyDifferentEchoID)];
300 memcpy(buffer_3, kIpHeader, sizeof(kIpHeader));
301 memcpy(buffer_3 + sizeof(kIpHeader), kIcmpEchoReplyDifferentEchoID,
Samuel Tanf66080e2015-06-18 15:53:00 -0700302 sizeof(kIcmpEchoReplyDifferentEchoID));
303 InputData data_3(reinterpret_cast<unsigned char*>(buffer_3),
304 sizeof(buffer_3));
305 EXPECT_CALL(*this, ResultCallback(_)).Times(0);
306 EXPECT_CALL(*icmp_, Stop()).Times(0);
307 OnEchoReplyReceived(&data_3);
308 EXPECT_EQ(3, GetSeqNumToSentRecvTime()->size());
309 EXPECT_EQ(2, GetReceivedEchoReplySeqNumbers()->size());
310
311 // Receive third reply, which concludes the ICMP session.
312 testing_clock_.Advance(kRecvTime3 - now);
313 now = testing_clock_.NowTicks();
Samuel Tanc3227bb2015-08-28 16:40:07 -0700314 uint8_t buffer_4[sizeof(kIpHeader) + sizeof(kIcmpEchoReply3)];
315 memcpy(buffer_4, kIpHeader, sizeof(kIpHeader));
316 memcpy(buffer_4 + sizeof(kIpHeader), kIcmpEchoReply3,
317 sizeof(kIcmpEchoReply3));
Samuel Tanf66080e2015-06-18 15:53:00 -0700318 InputData data_4(reinterpret_cast<unsigned char*>(buffer_4),
319 sizeof(buffer_4));
320 EXPECT_CALL(*this, ResultCallback(expected_result));
321 EXPECT_CALL(*icmp_, Stop());
322 OnEchoReplyReceived(&data_4);
323 EXPECT_EQ(3, GetSeqNumToSentRecvTime()->size());
324 EXPECT_EQ(3, GetReceivedEchoReplySeqNumbers()->size());
325 EXPECT_TRUE(ReceivedEchoReplySeqNumbersContains(kIcmpEchoReply3_SeqNum));
326
327 VerifyIcmpSessionStopped();
328}
329
330TEST_F(IcmpSessionTest, SessionTimeoutOrInterrupted) {
331 // Test a failed ICMP session where we neither send out all echo requests nor
332 // receive all echo replies before stopping the ICMP session (because of a
333 // timeout or a manually-triggered stop). Moreover, test that echo requests
334 // that are sent unsuccessfully are sent again.
335
336 base::TimeTicks now = testing_clock_.NowTicks();
337 base::TimeTicks kSentTime1 = base::TimeTicks::FromInternalValue(10);
338 base::TimeTicks kSentTime2 = base::TimeTicks::FromInternalValue(20);
339 base::TimeTicks kRecvTime1 = base::TimeTicks::FromInternalValue(30);
340 base::TimeTicks kResendTime1 = base::TimeTicks::FromInternalValue(40);
341
342 IcmpSession::IcmpSessionResult expected_partial_result;
343 expected_partial_result.push_back(kRecvTime1 - kSentTime1);
344 expected_partial_result.push_back(base::TimeDelta());
345
346 // Initiate session.
347 IPAddress ipv4_destination(IPAddress::kFamilyIPv4);
348 EXPECT_TRUE(ipv4_destination.SetAddressFromString(kIPAddress));
349 StartAndVerify(ipv4_destination);
350
351 // Send the first echo request successfully.
352 testing_clock_.Advance(kSentTime1 - now);
353 now = testing_clock_.NowTicks();
354 SetCurrentSequenceNumber(kIcmpEchoReply1_SeqNum);
355 EXPECT_CALL(dispatcher_,
356 PostDelayedTask(_, GetEchoRequestIntervalSeconds() * 1000));
357 TransmitEchoRequestTask(ipv4_destination, true);
358 EXPECT_TRUE(GetReceivedEchoReplySeqNumbers()->empty());
359 EXPECT_EQ(1, GetSeqNumToSentRecvTime()->size());
360 EXPECT_TRUE(SeqNumToSentRecvTimeContains(kIcmpEchoReply1_SeqNum));
361 EXPECT_EQ(now, GetSeqNumToSentRecvTime()->at(kIcmpEchoReply1_SeqNum).first);
362 EXPECT_EQ(kIcmpEchoReply2_SeqNum, GetCurrentSequenceNumber());
363
364 // Send the second echo request unsuccessfully.
365 testing_clock_.Advance(kSentTime2 - now);
366 now = testing_clock_.NowTicks();
367 EXPECT_CALL(dispatcher_,
368 PostDelayedTask(_, GetEchoRequestIntervalSeconds() * 1000));
369 TransmitEchoRequestTask(ipv4_destination, false);
370 EXPECT_TRUE(GetReceivedEchoReplySeqNumbers()->empty());
371 EXPECT_EQ(1, GetSeqNumToSentRecvTime()->size());
372 EXPECT_FALSE(SeqNumToSentRecvTimeContains(kIcmpEchoReply2_SeqNum));
373 // The sequence number should still be incremented when we fail to transmit an
374 // echo request.
375 EXPECT_EQ(kIcmpEchoReply3_SeqNum, GetCurrentSequenceNumber());
376
377 // Receive first reply.
378 testing_clock_.Advance(kRecvTime1 - now);
379 now = testing_clock_.NowTicks();
Samuel Tanc3227bb2015-08-28 16:40:07 -0700380 uint8_t buffer_1[sizeof(kIpHeader) + sizeof(kIcmpEchoReply1)];
381 memcpy(buffer_1, kIpHeader, sizeof(kIpHeader));
382 memcpy(buffer_1 + sizeof(kIpHeader), kIcmpEchoReply1,
383 sizeof(kIcmpEchoReply1));
Samuel Tanf66080e2015-06-18 15:53:00 -0700384 InputData data_1(reinterpret_cast<unsigned char*>(buffer_1),
385 sizeof(buffer_1));
386 EXPECT_CALL(*this, ResultCallback(_)).Times(0);
387 OnEchoReplyReceived(&data_1);
388 EXPECT_EQ(1, GetReceivedEchoReplySeqNumbers()->size());
389 EXPECT_TRUE(ReceivedEchoReplySeqNumbersContains(kIcmpEchoReply1_SeqNum));
390
391 // Resend second echo request successfully.
392 testing_clock_.Advance(kResendTime1 - now);
393 now = testing_clock_.NowTicks();
394 EXPECT_CALL(dispatcher_,
395 PostDelayedTask(_, GetEchoRequestIntervalSeconds() * 1000));
396 TransmitEchoRequestTask(ipv4_destination, true);
397 EXPECT_EQ(1, GetReceivedEchoReplySeqNumbers()->size());
398 EXPECT_EQ(2, GetSeqNumToSentRecvTime()->size());
399 EXPECT_TRUE(SeqNumToSentRecvTimeContains(kIcmpEchoReply3_SeqNum));
400 EXPECT_EQ(now, GetSeqNumToSentRecvTime()->at(kIcmpEchoReply3_SeqNum).first);
401 EXPECT_EQ(kIcmpEchoReply3_SeqNum + 1, GetCurrentSequenceNumber());
402
Samuel Tan42c33a42015-07-14 17:52:57 -0700403 // Timeout triggered, so report partial results.
Samuel Tanf66080e2015-06-18 15:53:00 -0700404 EXPECT_CALL(*this, ResultCallback(expected_partial_result));
405 EXPECT_CALL(*icmp_, Stop());
Samuel Tan42c33a42015-07-14 17:52:57 -0700406 ReportResultAndStopSession();
Samuel Tanf66080e2015-06-18 15:53:00 -0700407 EXPECT_EQ(2, GetSeqNumToSentRecvTime()->size());
408 EXPECT_EQ(1, GetReceivedEchoReplySeqNumbers()->size());
Samuel Tan42c33a42015-07-14 17:52:57 -0700409 VerifyIcmpSessionStopped();
410}
Samuel Tanf66080e2015-06-18 15:53:00 -0700411
Samuel Tan42c33a42015-07-14 17:52:57 -0700412TEST_F(IcmpSessionTest, DoNotReportResultsOnStop) {
413 // Initiate session.
414 IPAddress ipv4_destination(IPAddress::kFamilyIPv4);
415 EXPECT_TRUE(ipv4_destination.SetAddressFromString(kIPAddress));
416 StartAndVerify(ipv4_destination);
417
418 // Session interrupted manually by calling Stop(), so do not report results.
419 EXPECT_CALL(*this, ResultCallback(_)).Times(0);
420 EXPECT_CALL(*icmp_, Stop());
421 Stop();
Samuel Tanf66080e2015-06-18 15:53:00 -0700422 VerifyIcmpSessionStopped();
423}
424
Samuel Tan83375982015-06-30 14:35:20 -0700425TEST_F(IcmpSessionTest, AnyRepliesReceived) {
426 IcmpSession::IcmpSessionResult none_sent;
427 EXPECT_FALSE(IcmpSession::AnyRepliesReceived(none_sent));
428
429 IcmpSession::IcmpSessionResult two_sent_none_received;
430 two_sent_none_received.push_back(base::TimeDelta());
431 two_sent_none_received.push_back(base::TimeDelta());
432 EXPECT_FALSE(IcmpSession::AnyRepliesReceived(two_sent_none_received));
433
434 IcmpSession::IcmpSessionResult one_sent_one_received;
435 one_sent_one_received.push_back(base::TimeDelta::FromSeconds(10));
436 EXPECT_TRUE(IcmpSession::AnyRepliesReceived(one_sent_one_received));
437
438 IcmpSession::IcmpSessionResult two_sent_one_received;
439 two_sent_one_received.push_back(base::TimeDelta::FromSeconds(20));
440 two_sent_one_received.push_back(base::TimeDelta());
441 EXPECT_TRUE(IcmpSession::AnyRepliesReceived(two_sent_one_received));
442}
443
Samuel Tanf25d4262015-08-03 16:03:31 -0700444TEST_F(IcmpSessionTest, IsPacketLossPercentageGreaterThan) {
445 // If we sent no echo requests out, we expect no replies, therefore we have
446 // 0% packet loss.
447 IcmpSession::IcmpSessionResult none_sent_none_received;
448 EXPECT_FALSE(IcmpSession::IsPacketLossPercentageGreaterThan(
449 none_sent_none_received, 0));
450
451 // If we receive all replies, we experience 0% packet loss.
452 IcmpSession::IcmpSessionResult three_sent_three_received;
453 three_sent_three_received.push_back(base::TimeDelta::FromSeconds(10));
454 three_sent_three_received.push_back(base::TimeDelta::FromSeconds(10));
455 three_sent_three_received.push_back(base::TimeDelta::FromSeconds(10));
456 EXPECT_FALSE(IcmpSession::IsPacketLossPercentageGreaterThan(
457 three_sent_three_received, 0));
458
459 // If we sent 3 requests and received 2 replies, we have ~33% packet loss.
460 IcmpSession::IcmpSessionResult three_sent_two_received;
461 three_sent_two_received.push_back(base::TimeDelta::FromSeconds(10));
462 three_sent_two_received.push_back(base::TimeDelta::FromSeconds(10));
463 three_sent_two_received.push_back(base::TimeDelta());
464 EXPECT_FALSE(IcmpSession::IsPacketLossPercentageGreaterThan(
465 three_sent_two_received, 60));
466 EXPECT_FALSE(IcmpSession::IsPacketLossPercentageGreaterThan(
467 three_sent_two_received, 33));
468 EXPECT_TRUE(IcmpSession::IsPacketLossPercentageGreaterThan(
469 three_sent_two_received, 32));
470 EXPECT_TRUE(IcmpSession::IsPacketLossPercentageGreaterThan(
471 three_sent_two_received, 10));
472}
473
Samuel Tanf66080e2015-06-18 15:53:00 -0700474} // namespace shill