OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <queue> | 5 #include <queue> |
6 | 6 |
7 #include "base/memory/ref_counted.h" | 7 #include "base/memory/ref_counted.h" |
8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/time/clock.h" |
| 10 #include "base/time/default_clock.h" |
| 11 #include "base/timer/mock_timer.h" |
9 #include "net/base/rand_callback.h" | 12 #include "net/base/rand_callback.h" |
10 #include "net/base/test_completion_callback.h" | 13 #include "net/base/test_completion_callback.h" |
11 #include "net/dns/mdns_client_impl.h" | 14 #include "net/dns/mdns_client_impl.h" |
12 #include "net/dns/mock_mdns_socket_factory.h" | 15 #include "net/dns/mock_mdns_socket_factory.h" |
13 #include "net/dns/record_rdata.h" | 16 #include "net/dns/record_rdata.h" |
14 #include "net/udp/udp_client_socket.h" | 17 #include "net/udp/udp_client_socket.h" |
15 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
17 | 20 |
18 using ::testing::Invoke; | 21 using ::testing::Invoke; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 0xc0, 0x14, // Pointer to "._tcp.local" | 218 0xc0, 0x14, // Pointer to "._tcp.local" |
216 0x00, 0x0c, // TYPE is PTR. | 219 0x00, 0x0c, // TYPE is PTR. |
217 0x00, 0x01, // CLASS is IN. | 220 0x00, 0x01, // CLASS is IN. |
218 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. | 221 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
219 0x24, 0x74, | 222 0x24, 0x74, |
220 0x00, 0x08, // RDLENGTH is 8 bytes. | 223 0x00, 0x08, // RDLENGTH is 8 bytes. |
221 0x05, 'z', 'z', 'z', 'z', 'z', | 224 0x05, 'z', 'z', 'z', 'z', 'z', |
222 0xc0, 0x32 | 225 0xc0, 0x32 |
223 }; | 226 }; |
224 | 227 |
| 228 const uint8 kSamplePacket3[] = { |
| 229 // Header |
| 230 0x00, 0x00, // ID is zeroed out |
| 231 0x81, 0x80, // Standard query response, RA, no error |
| 232 0x00, 0x00, // No questions (for simplicity) |
| 233 0x00, 0x02, // 2 RRs (answers) |
| 234 0x00, 0x00, // 0 authority RRs |
| 235 0x00, 0x00, // 0 additional RRs |
| 236 |
| 237 // Answer 1 |
| 238 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', |
| 239 0x04, '_', 't', 'c', 'p', 0x05, 'l', 'o', |
| 240 'c', 'a', 'l', 0x00, 0x00, 0x0c, // TYPE is PTR. |
| 241 0x00, 0x01, // CLASS is IN. |
| 242 0x00, 0x00, // TTL (4 bytes) is 1 second; |
| 243 0x00, 0x01, 0x00, 0x08, // RDLENGTH is 8 bytes. |
| 244 0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x0c, |
| 245 |
| 246 // Answer 2 |
| 247 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', |
| 248 'r', 0xc0, 0x14, // Pointer to "._tcp.local" |
| 249 0x00, 0x0c, // TYPE is PTR. |
| 250 0x00, 0x01, // CLASS is IN. |
| 251 0x00, 0x00, // TTL (4 bytes) is 3 seconds. |
| 252 0x00, 0x03, 0x00, 0x08, // RDLENGTH is 8 bytes. |
| 253 0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x32 |
| 254 }; |
| 255 |
225 const uint8 kQueryPacketPrivet[] = { | 256 const uint8 kQueryPacketPrivet[] = { |
226 // Header | 257 // Header |
227 0x00, 0x00, // ID is zeroed out | 258 0x00, 0x00, // ID is zeroed out |
228 0x00, 0x00, // No flags. | 259 0x00, 0x00, // No flags. |
229 0x00, 0x01, // One question. | 260 0x00, 0x01, // One question. |
230 0x00, 0x00, // 0 RRs (answers) | 261 0x00, 0x00, // 0 RRs (answers) |
231 0x00, 0x00, // 0 authority RRs | 262 0x00, 0x00, // 0 authority RRs |
232 0x00, 0x00, // 0 additional RRs | 263 0x00, 0x00, // 0 additional RRs |
233 | 264 |
234 // Question | 265 // Question |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 const std::string& ptrdomain() { return ptrdomain_; } | 413 const std::string& ptrdomain() { return ptrdomain_; } |
383 int ttl() { return ttl_; } | 414 int ttl() { return ttl_; } |
384 | 415 |
385 private: | 416 private: |
386 bool set_; | 417 bool set_; |
387 std::string name_; | 418 std::string name_; |
388 std::string ptrdomain_; | 419 std::string ptrdomain_; |
389 int ttl_; | 420 int ttl_; |
390 }; | 421 }; |
391 | 422 |
| 423 class MockClock : public base::DefaultClock { |
| 424 public: |
| 425 MockClock() : base::DefaultClock() {} |
| 426 virtual ~MockClock() {} |
| 427 |
| 428 MOCK_METHOD0(Now, base::Time()); |
| 429 |
| 430 private: |
| 431 DISALLOW_COPY_AND_ASSIGN(MockClock); |
| 432 }; |
| 433 |
| 434 class MockTimer : public base::MockTimer { |
| 435 public: |
| 436 MockTimer() : base::MockTimer(false, false) {} |
| 437 ~MockTimer() {} |
| 438 |
| 439 void Start(const tracked_objects::Location& posted_from, |
| 440 base::TimeDelta delay, |
| 441 const base::Closure& user_task) { |
| 442 StartObserver(posted_from, delay, user_task); |
| 443 base::MockTimer::Start(posted_from, delay, user_task); |
| 444 } |
| 445 |
| 446 // StartObserver is invoked when MockTimer::Start() is called. |
| 447 // Does not replace the behavior of MockTimer::Start(). |
| 448 MOCK_METHOD3(StartObserver, |
| 449 void(const tracked_objects::Location& posted_from, |
| 450 base::TimeDelta delay, |
| 451 const base::Closure& user_task)); |
| 452 |
| 453 private: |
| 454 DISALLOW_COPY_AND_ASSIGN(MockTimer); |
| 455 }; |
| 456 |
| 457 } // namespace |
| 458 |
392 class MDnsTest : public ::testing::Test { | 459 class MDnsTest : public ::testing::Test { |
393 public: | 460 public: |
394 virtual void SetUp() override; | 461 void SetUp() override; |
395 void DeleteTransaction(); | 462 void DeleteTransaction(); |
396 void DeleteBothListeners(); | 463 void DeleteBothListeners(); |
397 void RunFor(base::TimeDelta time_period); | 464 void RunFor(base::TimeDelta time_period); |
398 void Stop(); | 465 void Stop(); |
399 | 466 |
400 MOCK_METHOD2(MockableRecordCallback, void(MDnsTransaction::Result result, | 467 MOCK_METHOD2(MockableRecordCallback, void(MDnsTransaction::Result result, |
401 const RecordParsed* record)); | 468 const RecordParsed* record)); |
402 | 469 |
403 MOCK_METHOD2(MockableRecordCallback2, void(MDnsTransaction::Result result, | 470 MOCK_METHOD2(MockableRecordCallback2, void(MDnsTransaction::Result result, |
404 const RecordParsed* record)); | 471 const RecordParsed* record)); |
405 | 472 |
406 | |
407 protected: | 473 protected: |
408 void ExpectPacket(const uint8* packet, unsigned size); | 474 void ExpectPacket(const uint8* packet, unsigned size); |
409 void SimulatePacketReceive(const uint8* packet, unsigned size); | 475 void SimulatePacketReceive(const uint8* packet, unsigned size); |
410 | 476 |
411 MDnsClientImpl test_client_; | 477 MDnsClientImpl test_client_; |
412 IPEndPoint mdns_ipv4_endpoint_; | 478 IPEndPoint mdns_ipv4_endpoint_; |
413 StrictMock<MockMDnsSocketFactory> socket_factory_; | 479 StrictMock<MockMDnsSocketFactory> socket_factory_; |
414 | 480 |
415 // Transactions and listeners that can be deleted by class methods for | 481 // Transactions and listeners that can be deleted by class methods for |
416 // reentrancy tests. | 482 // reentrancy tests. |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::Stop), | 604 .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::Stop), |
539 Invoke(&record_privet2, | 605 Invoke(&record_privet2, |
540 &PtrRecordCopyContainer::SaveWithDummyArg))); | 606 &PtrRecordCopyContainer::SaveWithDummyArg))); |
541 | 607 |
542 RunFor(base::TimeDelta::FromSeconds(record_privet.ttl() + 1)); | 608 RunFor(base::TimeDelta::FromSeconds(record_privet.ttl() + 1)); |
543 | 609 |
544 EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local", | 610 EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local", |
545 "hello._privet._tcp.local")); | 611 "hello._privet._tcp.local")); |
546 } | 612 } |
547 | 613 |
| 614 // Ensure that the cleanup task scheduler won't schedule cleanup tasks in the |
| 615 // past if the system clock creeps past the expiration time while in the |
| 616 // cleanup dispatcher. |
| 617 TEST_F(MDnsTest, CacheCleanupWithShortTTL) { |
| 618 // Use a nonzero starting time as a base. |
| 619 base::Time start_time = base::Time() + base::TimeDelta::FromSeconds(1); |
| 620 |
| 621 MockClock* clock = new MockClock; |
| 622 MockTimer* timer = new MockTimer; |
| 623 |
| 624 EXPECT_CALL(*timer, StartObserver(_, _, _)).Times(1); |
| 625 EXPECT_CALL(*clock, Now()) |
| 626 .Times(3) |
| 627 .WillRepeatedly(Return(start_time)) |
| 628 .RetiresOnSaturation(); |
| 629 |
| 630 test_client_.core()->set_cleanup_timer_for_test(make_scoped_ptr(timer)); |
| 631 test_client_.core()->set_clock_for_test(make_scoped_ptr(clock)); |
| 632 |
| 633 // Receive two records with different TTL values. |
| 634 // TTL(privet)=1.0s |
| 635 // TTL(printer)=3.0s |
| 636 StrictMock<MockListenerDelegate> delegate_privet; |
| 637 StrictMock<MockListenerDelegate> delegate_printer; |
| 638 |
| 639 PtrRecordCopyContainer record_privet; |
| 640 PtrRecordCopyContainer record_printer; |
| 641 |
| 642 scoped_ptr<MDnsListener> listener_privet = test_client_.CreateListener( |
| 643 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet); |
| 644 scoped_ptr<MDnsListener> listener_printer = test_client_.CreateListener( |
| 645 dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer); |
| 646 |
| 647 ASSERT_TRUE(listener_privet->Start()); |
| 648 ASSERT_TRUE(listener_printer->Start()); |
| 649 |
| 650 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
| 651 .Times(Exactly(1)); |
| 652 EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
| 653 .Times(Exactly(1)); |
| 654 |
| 655 SimulatePacketReceive(kSamplePacket3, sizeof(kSamplePacket3)); |
| 656 |
| 657 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _)) |
| 658 .Times(Exactly(1)); |
| 659 |
| 660 // Set the clock to 2.0s, which should clean up the 'privet' record, but not |
| 661 // the printer. The mock clock will change Now() mid-execution from 2s to 4s. |
| 662 // Note: expectations are FILO-ordered -- t+2 seconds is returned, then t+4. |
| 663 EXPECT_CALL(*clock, Now()) |
| 664 .WillOnce(Return(start_time + base::TimeDelta::FromSeconds(4))) |
| 665 .RetiresOnSaturation(); |
| 666 EXPECT_CALL(*clock, Now()) |
| 667 .WillOnce(Return(start_time + base::TimeDelta::FromSeconds(2))) |
| 668 .RetiresOnSaturation(); |
| 669 |
| 670 EXPECT_CALL(*timer, StartObserver(_, base::TimeDelta(), _)); |
| 671 |
| 672 timer->Fire(); |
| 673 } |
| 674 |
548 TEST_F(MDnsTest, MalformedPacket) { | 675 TEST_F(MDnsTest, MalformedPacket) { |
549 StrictMock<MockListenerDelegate> delegate_printer; | 676 StrictMock<MockListenerDelegate> delegate_printer; |
550 | 677 |
551 PtrRecordCopyContainer record_printer; | 678 PtrRecordCopyContainer record_printer; |
552 | 679 |
553 scoped_ptr<MDnsListener> listener_printer = | 680 scoped_ptr<MDnsListener> listener_printer = |
554 test_client_.CreateListener(dns_protocol::kTypePTR, "_printer._tcp.local", | 681 test_client_.CreateListener(dns_protocol::kTypePTR, "_printer._tcp.local", |
555 &delegate_printer); | 682 &delegate_printer); |
556 | 683 |
557 ASSERT_TRUE(listener_printer->Start()); | 684 ASSERT_TRUE(listener_printer->Start()); |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1080 MOCK_METHOD1(OnConnectionError, void(int error)); | 1207 MOCK_METHOD1(OnConnectionError, void(int error)); |
1081 }; | 1208 }; |
1082 | 1209 |
1083 class MDnsConnectionTest : public ::testing::Test { | 1210 class MDnsConnectionTest : public ::testing::Test { |
1084 public: | 1211 public: |
1085 MDnsConnectionTest() : connection_(&delegate_) { | 1212 MDnsConnectionTest() : connection_(&delegate_) { |
1086 } | 1213 } |
1087 | 1214 |
1088 protected: | 1215 protected: |
1089 // Follow successful connection initialization. | 1216 // Follow successful connection initialization. |
1090 virtual void SetUp() override { | 1217 void SetUp() override { |
1091 socket_ipv4_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV4); | 1218 socket_ipv4_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV4); |
1092 socket_ipv6_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV6); | 1219 socket_ipv6_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV6); |
1093 factory_.PushSocket(socket_ipv6_); | 1220 factory_.PushSocket(socket_ipv6_); |
1094 factory_.PushSocket(socket_ipv4_); | 1221 factory_.PushSocket(socket_ipv4_); |
1095 sample_packet_ = MakeString(kSamplePacket1, sizeof(kSamplePacket1)); | 1222 sample_packet_ = MakeString(kSamplePacket1, sizeof(kSamplePacket1)); |
1096 sample_buffer_ = new StringIOBuffer(sample_packet_); | 1223 sample_buffer_ = new StringIOBuffer(sample_packet_); |
1097 } | 1224 } |
1098 | 1225 |
1099 bool InitConnection() { | 1226 bool InitConnection() { |
1100 return connection_.Init(&factory_); | 1227 return connection_.Init(&factory_); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 EXPECT_CALL(*socket_ipv4_, | 1339 EXPECT_CALL(*socket_ipv4_, |
1213 SendToInternal(sample_packet_, "224.0.0.251:5353", _)) | 1340 SendToInternal(sample_packet_, "224.0.0.251:5353", _)) |
1214 .Times(0); | 1341 .Times(0); |
1215 // Expect call for the second IPv6 packed. | 1342 // Expect call for the second IPv6 packed. |
1216 EXPECT_CALL(*socket_ipv6_, | 1343 EXPECT_CALL(*socket_ipv6_, |
1217 SendToInternal(sample_packet_, "[ff02::fb]:5353", _)) | 1344 SendToInternal(sample_packet_, "[ff02::fb]:5353", _)) |
1218 .WillOnce(Return(OK)); | 1345 .WillOnce(Return(OK)); |
1219 callback.Run(OK); | 1346 callback.Run(OK); |
1220 } | 1347 } |
1221 | 1348 |
1222 } // namespace | |
1223 | |
1224 } // namespace net | 1349 } // namespace net |
OLD | NEW |