1 // 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 // 16 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 26 using base::Bind; 27 using base::Unretained; 28 using testing::_; 29 using testing::NiceMock; 30 using testing::Return; 31 using testing::StrictMock; 32 using testing::Test; 33 34 namespace shill { 35 36 namespace { 37 38 // Note: this header is given in network byte order, since 39 // IcmpSession::OnEchoReplyReceived expects to receive a raw IP packet. 40 const 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}; 43 // 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. 46 const uint8_t kIcmpEchoReply1[] = {0x00, 0x00, 0xf7, 0xff, 47 0x00, 0x00, 0x08, 0x00}; 48 const uint16_t kIcmpEchoReply1_SeqNum = 0x08; 49 const uint8_t kIcmpEchoReply2[] = {0x00, 0x00, 0xf6, 0xff, 50 0x00, 0x00, 0x09, 0x00}; 51 const uint16_t kIcmpEchoReply2_SeqNum = 0x09; 52 const uint8_t kIcmpEchoReply3[] = {0x00, 0x00, 0xf5, 0xff, 53 0x00, 0x00, 0x0a, 0x00}; 54 const 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). 58 const uint8_t kIcmpEchoReplyDifferentEchoID[] = {0x00, 0x00, 0xea, 0xff, 59 0x0e, 0x00, 0x0b, 0x00}; 60 61 } // namespace 62 63 MATCHER_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 69 class 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 132 void ReportResultAndStopSession() { 133 icmp_session_.ReportResultAndStopSession(); 134 } 135 136 void VerifyIcmpSessionStopped() { 137 EXPECT_TRUE(icmp_session_.timeout_callback_.IsCancelled()); 138 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 178 const char IcmpSessionTest::kIPAddress[] = "10.0.1.1"; 179 180 TEST_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 194 TEST_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 207 TEST_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 216 TEST_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(); 256 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)); 260 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(); 294 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)); 298 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(); 311 uint8_t buffer_3[sizeof(kIpHeader) + sizeof(kIcmpEchoReplyDifferentEchoID)]; 312 memcpy(buffer_3, kIpHeader, sizeof(kIpHeader)); 313 memcpy(buffer_3 + sizeof(kIpHeader), kIcmpEchoReplyDifferentEchoID, 314 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(); 326 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)); 330 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 342 TEST_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(); 392 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)); 396 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 415 // Timeout triggered, so report partial results. 416 EXPECT_CALL(*this, ResultCallback(expected_partial_result)); 417 EXPECT_CALL(*icmp_, Stop()); 418 ReportResultAndStopSession(); 419 EXPECT_EQ(2, GetSeqNumToSentRecvTime()->size()); 420 EXPECT_EQ(1, GetReceivedEchoReplySeqNumbers()->size()); 421 VerifyIcmpSessionStopped(); 422 } 423 424 TEST_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(); 434 VerifyIcmpSessionStopped(); 435 } 436 437 TEST_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 456 TEST_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 486 } // namespace shill 487