| 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..c754f70ad54f58fae2a277432734b6428a06727d 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;
|
| + 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.
|
| + 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,7 +470,6 @@ 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);
|
| @@ -545,6 +611,67 @@ 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;
|
| +
|
| + EXPECT_CALL(*timer, StartObserver(_, _, _)).Times(1);
|
| + EXPECT_CALL(*clock, Now())
|
| + .Times(3)
|
| + .WillRepeatedly(Return(start_time))
|
| + .RetiresOnSaturation();
|
| +
|
| + test_client_.core()->set_cleanup_timer_for_test(make_scoped_ptr(timer));
|
| + test_client_.core()->set_clock_for_test(make_scoped_ptr(clock));
|
| +
|
| + // 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;
|
|
|
| @@ -1087,7 +1214,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 +1346,4 @@ TEST_F(MDnsConnectionSendTest, SendQueued) {
|
| callback.Run(OK);
|
| }
|
|
|
| -} // namespace
|
| -
|
| } // namespace net
|
|
|