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