Chromium Code Reviews| Index: net/dns/mdns_client_unittest.cc |
| diff --git a/net/dns/mdns_client_unittest.cc b/net/dns/mdns_client_unittest.cc |
| index ba0308201bb1558be136a002193d8befcb3fc491..eaacee3e1d55239e43232f01836cf5d3192ddb1f 100644 |
| --- a/net/dns/mdns_client_unittest.cc |
| +++ b/net/dns/mdns_client_unittest.cc |
| @@ -6,6 +6,9 @@ |
| #include "base/memory/ref_counted.h" |
| #include "base/message_loop/message_loop.h" |
| +#include "base/time/clock.h" |
| +#include "base/time/default_clock.h" |
| +#include "base/timer/mock_timer.h" |
| #include "net/base/rand_callback.h" |
| #include "net/base/test_completion_callback.h" |
| #include "net/dns/mdns_client_impl.h" |
| @@ -222,6 +225,34 @@ const uint8 kSamplePacket2[] = { |
| 0xc0, 0x32 |
| }; |
| +const uint8 kSamplePacket3[] = { |
| + // Header |
| + 0x00, 0x00, // ID is zeroed out |
| + 0x81, 0x80, // Standard query response, RA, no error |
| + 0x00, 0x00, // No questions (for simplicity) |
| + 0x00, 0x02, // 2 RRs (answers) |
| + 0x00, 0x00, // 0 authority RRs |
| + 0x00, 0x00, // 0 additional RRs |
| + |
| + // Answer 1 |
| + 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', |
| + 0x04, '_', 't', 'c', 'p', 0x05, 'l', 'o', |
| + 'c', 'a', 'l', 0x00, 0x00, 0x0c, // TYPE is PTR. |
| + 0x00, 0x01, // CLASS is IN. |
| + 0x00, 0x00, // TTL (4 bytes) is 1 second; |
|
gene
2015/03/02 19:37:16
nit: can you move 0x00, 0x01 here from the line be
Kevin M
2015/03/02 20:23:46
Hmm, "git cl format" screwed this up.
I'll put in
|
| + 0x00, 0x01, 0x00, 0x08, // RDLENGTH is 8 bytes. |
| + 0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x0c, |
| + |
| + // Answer 2 |
| + 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', |
| + 'r', 0xc0, 0x14, // Pointer to "._tcp.local" |
| + 0x00, 0x0c, // TYPE is PTR. |
| + 0x00, 0x01, // CLASS is IN. |
| + 0x00, 0x00, // TTL (4 bytes) is 3 seconds. |
|
gene
2015/03/02 19:37:16
same here
Kevin M
2015/03/02 20:23:46
Done.
|
| + 0x00, 0x03, 0x00, 0x08, // RDLENGTH is 8 bytes. |
| + 0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x32 |
| +}; |
| + |
| const uint8 kQueryPacketPrivet[] = { |
| // Header |
| 0x00, 0x00, // ID is zeroed out |
| @@ -389,9 +420,45 @@ class PtrRecordCopyContainer { |
| int ttl_; |
| }; |
| +class MockClock : public base::DefaultClock { |
| + public: |
| + MockClock() : base::DefaultClock() {} |
| + virtual ~MockClock() {} |
| + |
| + MOCK_METHOD0(Now, base::Time()); |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(MockClock); |
| +}; |
| + |
| +class MockTimer : public base::MockTimer { |
| + public: |
| + MockTimer() : base::MockTimer(false, false) {} |
| + ~MockTimer() {} |
| + |
| + void Start(const tracked_objects::Location& posted_from, |
| + base::TimeDelta delay, |
| + const base::Closure& user_task) { |
| + StartObserver(posted_from, delay, user_task); |
| + base::MockTimer::Start(posted_from, delay, user_task); |
| + } |
| + |
| + // StartObserver is invoked when MockTimer::Start() is called. |
| + // Does not replace the behavior of MockTimer::Start(). |
| + MOCK_METHOD3(StartObserver, |
| + void(const tracked_objects::Location& posted_from, |
| + base::TimeDelta delay, |
| + const base::Closure& user_task)); |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(MockTimer); |
| +}; |
| + |
| +} // namespace |
| + |
| class MDnsTest : public ::testing::Test { |
| public: |
| - virtual void SetUp() override; |
| + void SetUp() override; |
| void DeleteTransaction(); |
| void DeleteBothListeners(); |
| void RunFor(base::TimeDelta time_period); |
| @@ -403,12 +470,11 @@ class MDnsTest : public ::testing::Test { |
| MOCK_METHOD2(MockableRecordCallback2, void(MDnsTransaction::Result result, |
| const RecordParsed* record)); |
| - |
| protected: |
| void ExpectPacket(const uint8* packet, unsigned size); |
| void SimulatePacketReceive(const uint8* packet, unsigned size); |
| - MDnsClientImpl test_client_; |
| + scoped_ptr<MDnsClientImpl> test_client_; |
| IPEndPoint mdns_ipv4_endpoint_; |
| StrictMock<MockMDnsSocketFactory> socket_factory_; |
| @@ -429,7 +495,8 @@ class MockListenerDelegate : public MDnsListener::Delegate { |
| }; |
| void MDnsTest::SetUp() { |
| - test_client_.StartListening(&socket_factory_); |
| + test_client_.reset(new MDnsClientImpl()); |
| + test_client_->StartListening(&socket_factory_); |
| } |
| void MDnsTest::SimulatePacketReceive(const uint8* packet, unsigned size) { |
| @@ -471,12 +538,10 @@ TEST_F(MDnsTest, PassiveListeners) { |
| PtrRecordCopyContainer record_privet; |
| PtrRecordCopyContainer record_printer; |
| - scoped_ptr<MDnsListener> listener_privet = |
| - test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| - &delegate_privet); |
| - scoped_ptr<MDnsListener> listener_printer = |
| - test_client_.CreateListener(dns_protocol::kTypePTR, "_printer._tcp.local", |
| - &delegate_printer); |
| + scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener( |
| + dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet); |
| + scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener( |
| + dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer); |
| ASSERT_TRUE(listener_privet->Start()); |
| ASSERT_TRUE(listener_printer->Start()); |
| @@ -516,7 +581,7 @@ TEST_F(MDnsTest, PassiveListenersCacheCleanup) { |
| PtrRecordCopyContainer record_privet2; |
| scoped_ptr<MDnsListener> listener_privet = |
| - test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| + test_client_->CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| &delegate_privet); |
| ASSERT_TRUE(listener_privet->Start()); |
| @@ -545,14 +610,75 @@ TEST_F(MDnsTest, PassiveListenersCacheCleanup) { |
| "hello._privet._tcp.local")); |
| } |
| +// Ensure that the cleanup task scheduler won't schedule cleanup tasks in the |
| +// past if the system clock creeps past the expiration time while in the |
| +// cleanup dispatcher. |
| +TEST_F(MDnsTest, CacheCleanupWithShortTTL) { |
| + // Use a nonzero starting time as a base. |
| + base::Time start_time = base::Time() + base::TimeDelta::FromSeconds(1); |
| + |
| + MockClock* clock = new MockClock; |
| + MockTimer* timer = new MockTimer; |
| + |
| + test_client_.reset( |
| + new MDnsClientImpl(make_scoped_ptr(clock), make_scoped_ptr(timer))); |
| + test_client_->StartListening(&socket_factory_); |
| + |
| + EXPECT_CALL(*timer, StartObserver(_, _, _)).Times(1); |
| + EXPECT_CALL(*clock, Now()) |
| + .Times(3) |
| + .WillRepeatedly(Return(start_time)) |
| + .RetiresOnSaturation(); |
| + |
| + // Receive two records with different TTL values. |
| + // TTL(privet)=1.0s |
| + // TTL(printer)=3.0s |
| + StrictMock<MockListenerDelegate> delegate_privet; |
| + StrictMock<MockListenerDelegate> delegate_printer; |
| + |
| + PtrRecordCopyContainer record_privet; |
| + PtrRecordCopyContainer record_printer; |
| + |
| + scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener( |
| + dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet); |
| + scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener( |
| + dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer); |
| + |
| + ASSERT_TRUE(listener_privet->Start()); |
| + ASSERT_TRUE(listener_printer->Start()); |
| + |
| + EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
| + .Times(Exactly(1)); |
| + EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
| + .Times(Exactly(1)); |
| + |
| + SimulatePacketReceive(kSamplePacket3, sizeof(kSamplePacket3)); |
| + |
| + EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _)) |
| + .Times(Exactly(1)); |
| + |
| + // Set the clock to 2.0s, which should clean up the 'privet' record, but not |
| + // the printer. The mock clock will change Now() mid-execution from 2s to 4s. |
| + // Note: expectations are FILO-ordered -- t+2 seconds is returned, then t+4. |
| + EXPECT_CALL(*clock, Now()) |
| + .WillOnce(Return(start_time + base::TimeDelta::FromSeconds(4))) |
| + .RetiresOnSaturation(); |
| + EXPECT_CALL(*clock, Now()) |
| + .WillOnce(Return(start_time + base::TimeDelta::FromSeconds(2))) |
| + .RetiresOnSaturation(); |
| + |
| + EXPECT_CALL(*timer, StartObserver(_, base::TimeDelta(), _)); |
| + |
| + timer->Fire(); |
| +} |
| + |
| TEST_F(MDnsTest, MalformedPacket) { |
| StrictMock<MockListenerDelegate> delegate_printer; |
| PtrRecordCopyContainer record_printer; |
| - scoped_ptr<MDnsListener> listener_printer = |
| - test_client_.CreateListener(dns_protocol::kTypePTR, "_printer._tcp.local", |
| - &delegate_printer); |
| + scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener( |
| + dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer); |
| ASSERT_TRUE(listener_printer->Start()); |
| @@ -582,7 +708,7 @@ TEST_F(MDnsTest, TransactionWithEmptyCache) { |
| ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
| scoped_ptr<MDnsTransaction> transaction_privet = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE | |
| @@ -607,7 +733,7 @@ TEST_F(MDnsTest, TransactionWithEmptyCache) { |
| TEST_F(MDnsTest, TransactionCacheOnlyNoResult) { |
| scoped_ptr<MDnsTransaction> transaction_privet = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_privet._tcp.local", |
| MDnsTransaction::QUERY_CACHE | |
| MDnsTransaction::SINGLE_RESULT, |
| @@ -625,7 +751,7 @@ TEST_F(MDnsTest, TransactionWithCache) { |
| // Listener to force the client to listen |
| StrictMock<MockListenerDelegate> delegate_irrelevant; |
| scoped_ptr<MDnsListener> listener_irrelevant = |
| - test_client_.CreateListener(dns_protocol::kTypeA, |
| + test_client_->CreateListener(dns_protocol::kTypeA, |
| "codereview.chromium.local", |
| &delegate_irrelevant); |
| @@ -641,7 +767,7 @@ TEST_F(MDnsTest, TransactionWithCache) { |
| &PtrRecordCopyContainer::SaveWithDummyArg)); |
| scoped_ptr<MDnsTransaction> transaction_privet = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE | |
| @@ -661,7 +787,7 @@ TEST_F(MDnsTest, AdditionalRecords) { |
| PtrRecordCopyContainer record_privet; |
| scoped_ptr<MDnsListener> listener_privet = |
| - test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| + test_client_->CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| &delegate_privet); |
| ASSERT_TRUE(listener_privet->Start()); |
| @@ -683,7 +809,7 @@ TEST_F(MDnsTest, TransactionTimeout) { |
| ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
| scoped_ptr<MDnsTransaction> transaction_privet = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE | |
| @@ -705,7 +831,7 @@ TEST_F(MDnsTest, TransactionMultipleRecords) { |
| ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
| scoped_ptr<MDnsTransaction> transaction_privet = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE , |
| @@ -742,7 +868,7 @@ TEST_F(MDnsTest, TransactionMultipleRecords) { |
| TEST_F(MDnsTest, TransactionReentrantDelete) { |
| ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
| - transaction_ = test_client_.CreateTransaction( |
| + transaction_ = test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE | |
| @@ -765,14 +891,14 @@ TEST_F(MDnsTest, TransactionReentrantDelete) { |
| TEST_F(MDnsTest, TransactionReentrantDeleteFromCache) { |
| StrictMock<MockListenerDelegate> delegate_irrelevant; |
| - scoped_ptr<MDnsListener> listener_irrelevant = test_client_.CreateListener( |
| + scoped_ptr<MDnsListener> listener_irrelevant = test_client_->CreateListener( |
| dns_protocol::kTypeA, "codereview.chromium.local", |
| &delegate_irrelevant); |
| ASSERT_TRUE(listener_irrelevant->Start()); |
| SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1)); |
| - transaction_ = test_client_.CreateTransaction( |
| + transaction_ = test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE, |
| @@ -792,7 +918,7 @@ TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) { |
| ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
| scoped_ptr<MDnsTransaction> transaction1 = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE | |
| @@ -801,7 +927,7 @@ TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) { |
| base::Unretained(this))); |
| scoped_ptr<MDnsTransaction> transaction2 = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_printer._tcp.local", |
| MDnsTransaction::QUERY_CACHE | |
| MDnsTransaction::SINGLE_RESULT, |
| @@ -826,7 +952,7 @@ TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) { |
| TEST_F(MDnsTest, GoodbyePacketNotification) { |
| StrictMock<MockListenerDelegate> delegate_privet; |
| - scoped_ptr<MDnsListener> listener_privet = test_client_.CreateListener( |
| + scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener( |
| dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet); |
| ASSERT_TRUE(listener_privet->Start()); |
| @@ -839,7 +965,7 @@ TEST_F(MDnsTest, GoodbyePacketRemoval) { |
| StrictMock<MockListenerDelegate> delegate_privet; |
| scoped_ptr<MDnsListener> listener_privet = |
| - test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| + test_client_->CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| &delegate_privet); |
| ASSERT_TRUE(listener_privet->Start()); |
| @@ -863,11 +989,11 @@ TEST_F(MDnsTest, GoodbyePacketRemoval) { |
| TEST_F(MDnsTest, ListenerReentrantDelete) { |
| StrictMock<MockListenerDelegate> delegate_privet; |
| - listener1_ = test_client_.CreateListener(dns_protocol::kTypePTR, |
| + listener1_ = test_client_->CreateListener(dns_protocol::kTypePTR, |
| "_privet._tcp.local", |
| &delegate_privet); |
| - listener2_ = test_client_.CreateListener(dns_protocol::kTypePTR, |
| + listener2_ = test_client_->CreateListener(dns_protocol::kTypePTR, |
| "_privet._tcp.local", |
| &delegate_privet); |
| @@ -897,7 +1023,7 @@ TEST_F(MDnsTest, DoubleRecordDisagreeing) { |
| StrictMock<MockListenerDelegate> delegate_privet; |
| scoped_ptr<MDnsListener> listener_privet = |
| - test_client_.CreateListener(dns_protocol::kTypeA, "privet.local", |
| + test_client_->CreateListener(dns_protocol::kTypeA, "privet.local", |
| &delegate_privet); |
| ASSERT_TRUE(listener_privet->Start()); |
| @@ -915,14 +1041,14 @@ TEST_F(MDnsTest, DoubleRecordDisagreeing) { |
| TEST_F(MDnsTest, NsecWithListener) { |
| StrictMock<MockListenerDelegate> delegate_privet; |
| scoped_ptr<MDnsListener> listener_privet = |
| - test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local", |
| + test_client_->CreateListener(dns_protocol::kTypeA, "_privet._tcp.local", |
| &delegate_privet); |
| // Test to make sure nsec callback is NOT called for PTR |
| // (which is marked as existing). |
| StrictMock<MockListenerDelegate> delegate_privet2; |
| scoped_ptr<MDnsListener> listener_privet2 = |
| - test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| + test_client_->CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| &delegate_privet2); |
| ASSERT_TRUE(listener_privet->Start()); |
| @@ -936,7 +1062,7 @@ TEST_F(MDnsTest, NsecWithListener) { |
| TEST_F(MDnsTest, NsecWithTransactionFromNetwork) { |
| scoped_ptr<MDnsTransaction> transaction_privet = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypeA, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE | |
| @@ -959,7 +1085,7 @@ TEST_F(MDnsTest, NsecWithTransactionFromCache) { |
| // Force mDNS to listen. |
| StrictMock<MockListenerDelegate> delegate_irrelevant; |
| scoped_ptr<MDnsListener> listener_irrelevant = |
| - test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| + test_client_->CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
| &delegate_irrelevant); |
| listener_irrelevant->Start(); |
| @@ -970,7 +1096,7 @@ TEST_F(MDnsTest, NsecWithTransactionFromCache) { |
| MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL)); |
| scoped_ptr<MDnsTransaction> transaction_privet_a = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypeA, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE | |
| @@ -984,7 +1110,7 @@ TEST_F(MDnsTest, NsecWithTransactionFromCache) { |
| // valid answer to the query |
| scoped_ptr<MDnsTransaction> transaction_privet_ptr = |
| - test_client_.CreateTransaction( |
| + test_client_->CreateTransaction( |
| dns_protocol::kTypePTR, "_privet._tcp.local", |
| MDnsTransaction::QUERY_NETWORK | |
| MDnsTransaction::QUERY_CACHE | |
| @@ -1000,7 +1126,7 @@ TEST_F(MDnsTest, NsecWithTransactionFromCache) { |
| TEST_F(MDnsTest, NsecConflictRemoval) { |
| StrictMock<MockListenerDelegate> delegate_privet; |
| scoped_ptr<MDnsListener> listener_privet = |
| - test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local", |
| + test_client_->CreateListener(dns_protocol::kTypeA, "_privet._tcp.local", |
| &delegate_privet); |
| ASSERT_TRUE(listener_privet->Start()); |
| @@ -1030,7 +1156,7 @@ TEST_F(MDnsTest, NsecConflictRemoval) { |
| TEST_F(MDnsTest, RefreshQuery) { |
| StrictMock<MockListenerDelegate> delegate_privet; |
| scoped_ptr<MDnsListener> listener_privet = |
| - test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local", |
| + test_client_->CreateListener(dns_protocol::kTypeA, "_privet._tcp.local", |
| &delegate_privet); |
| listener_privet->SetActiveRefresh(true); |
| @@ -1087,7 +1213,7 @@ class MDnsConnectionTest : public ::testing::Test { |
| protected: |
| // Follow successful connection initialization. |
| - virtual void SetUp() override { |
| + void SetUp() override { |
| socket_ipv4_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV4); |
| socket_ipv6_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV6); |
| factory_.PushSocket(socket_ipv6_); |
| @@ -1219,6 +1345,4 @@ TEST_F(MDnsConnectionSendTest, SendQueued) { |
| callback.Run(OK); |
| } |
| -} // namespace |
| - |
| } // namespace net |