Index: net/dns/mdns_client_unittest.cc |
diff --git a/net/dns/mdns_client_unittest.cc b/net/dns/mdns_client_unittest.cc |
deleted file mode 100644 |
index ba0308201bb1558be136a002193d8befcb3fc491..0000000000000000000000000000000000000000 |
--- a/net/dns/mdns_client_unittest.cc |
+++ /dev/null |
@@ -1,1224 +0,0 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include <queue> |
- |
-#include "base/memory/ref_counted.h" |
-#include "base/message_loop/message_loop.h" |
-#include "net/base/rand_callback.h" |
-#include "net/base/test_completion_callback.h" |
-#include "net/dns/mdns_client_impl.h" |
-#include "net/dns/mock_mdns_socket_factory.h" |
-#include "net/dns/record_rdata.h" |
-#include "net/udp/udp_client_socket.h" |
-#include "testing/gmock/include/gmock/gmock.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-using ::testing::Invoke; |
-using ::testing::InvokeWithoutArgs; |
-using ::testing::StrictMock; |
-using ::testing::NiceMock; |
-using ::testing::Exactly; |
-using ::testing::Return; |
-using ::testing::SaveArg; |
-using ::testing::_; |
- |
-namespace net { |
- |
-namespace { |
- |
-const uint8 kSamplePacket1[] = { |
- // 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, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds. |
- 0x24, 0x75, |
- 0x00, 0x08, // RDLENGTH is 8 bytes. |
- 0x05, 'h', 'e', 'l', 'l', 'o', |
- 0xc0, 0x32 |
-}; |
- |
-const uint8 kCorruptedPacketBadQuestion[] = { |
- // Header |
- 0x00, 0x00, // ID is zeroed out |
- 0x81, 0x80, // Standard query response, RA, no error |
- 0x00, 0x01, // One question |
- 0x00, 0x02, // 2 RRs (answers) |
- 0x00, 0x00, // 0 authority RRs |
- 0x00, 0x00, // 0 additional RRs |
- |
- // Question is corrupted and cannot be read. |
- 0x99, 'h', 'e', 'l', 'l', 'o', |
- 0x00, |
- 0x00, 0x00, |
- 0x00, 0x00, |
- |
- // 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, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
- 0x24, 0x74, |
- 0x00, 0x99, // RDLENGTH is impossible |
- 0x05, 'h', 'e', 'l', 'l', 'o', |
- 0xc0, 0x0c, |
- |
- // Answer 2 |
- 0x08, '_', 'p', 'r', // Useless trailing data. |
-}; |
- |
-const uint8 kCorruptedPacketUnsalvagable[] = { |
- // 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, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
- 0x24, 0x74, |
- 0x00, 0x99, // RDLENGTH is impossible |
- 0x05, 'h', 'e', 'l', 'l', 'o', |
- 0xc0, 0x0c, |
- |
- // Answer 2 |
- 0x08, '_', 'p', 'r', // Useless trailing data. |
-}; |
- |
-const uint8 kCorruptedPacketDoubleRecord[] = { |
- // 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 |
- 0x06, 'p', 'r', 'i', 'v', 'e', 't', |
- 0x05, 'l', 'o', 'c', 'a', 'l', |
- 0x00, |
- 0x00, 0x01, // TYPE is A. |
- 0x00, 0x01, // CLASS is IN. |
- 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
- 0x24, 0x74, |
- 0x00, 0x04, // RDLENGTH is 4 |
- 0x05, 0x03, |
- 0xc0, 0x0c, |
- |
- // Answer 2 -- Same key |
- 0x06, 'p', 'r', 'i', 'v', 'e', 't', |
- 0x05, 'l', 'o', 'c', 'a', 'l', |
- 0x00, |
- 0x00, 0x01, // TYPE is A. |
- 0x00, 0x01, // CLASS is IN. |
- 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
- 0x24, 0x74, |
- 0x00, 0x04, // RDLENGTH is 4 |
- 0x02, 0x03, |
- 0x04, 0x05, |
-}; |
- |
-const uint8 kCorruptedPacketSalvagable[] = { |
- // 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, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
- 0x24, 0x74, |
- 0x00, 0x08, // RDLENGTH is 8 bytes. |
- 0x99, 'h', 'e', 'l', 'l', 'o', // Bad RDATA format. |
- 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, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds. |
- 0x24, 0x75, |
- 0x00, 0x08, // RDLENGTH is 8 bytes. |
- 0x05, 'h', 'e', 'l', 'l', 'o', |
- 0xc0, 0x32 |
-}; |
- |
-const uint8 kSamplePacket2[] = { |
- // 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, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
- 0x24, 0x74, |
- 0x00, 0x08, // RDLENGTH is 8 bytes. |
- 0x05, 'z', 'z', 'z', 'z', 'z', |
- 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, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
- 0x24, 0x74, |
- 0x00, 0x08, // RDLENGTH is 8 bytes. |
- 0x05, 'z', 'z', 'z', 'z', 'z', |
- 0xc0, 0x32 |
-}; |
- |
-const uint8 kQueryPacketPrivet[] = { |
- // Header |
- 0x00, 0x00, // ID is zeroed out |
- 0x00, 0x00, // No flags. |
- 0x00, 0x01, // One question. |
- 0x00, 0x00, // 0 RRs (answers) |
- 0x00, 0x00, // 0 authority RRs |
- 0x00, 0x00, // 0 additional RRs |
- |
- // Question |
- // This part is echoed back from the respective query. |
- 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. |
-}; |
- |
-const uint8 kQueryPacketPrivetA[] = { |
- // Header |
- 0x00, 0x00, // ID is zeroed out |
- 0x00, 0x00, // No flags. |
- 0x00, 0x01, // One question. |
- 0x00, 0x00, // 0 RRs (answers) |
- 0x00, 0x00, // 0 authority RRs |
- 0x00, 0x00, // 0 additional RRs |
- |
- // Question |
- // This part is echoed back from the respective query. |
- 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', |
- 0x04, '_', 't', 'c', 'p', |
- 0x05, 'l', 'o', 'c', 'a', 'l', |
- 0x00, |
- 0x00, 0x01, // TYPE is A. |
- 0x00, 0x01, // CLASS is IN. |
-}; |
- |
-const uint8 kSamplePacketAdditionalOnly[] = { |
- // Header |
- 0x00, 0x00, // ID is zeroed out |
- 0x81, 0x80, // Standard query response, RA, no error |
- 0x00, 0x00, // No questions (for simplicity) |
- 0x00, 0x00, // 2 RRs (answers) |
- 0x00, 0x00, // 0 authority RRs |
- 0x00, 0x01, // 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, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
- 0x24, 0x74, |
- 0x00, 0x08, // RDLENGTH is 8 bytes. |
- 0x05, 'h', 'e', 'l', 'l', 'o', |
- 0xc0, 0x0c, |
-}; |
- |
-const uint8 kSamplePacketNsec[] = { |
- // Header |
- 0x00, 0x00, // ID is zeroed out |
- 0x81, 0x80, // Standard query response, RA, no error |
- 0x00, 0x00, // No questions (for simplicity) |
- 0x00, 0x01, // 1 RR (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, 0x2f, // TYPE is NSEC. |
- 0x00, 0x01, // CLASS is IN. |
- 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. |
- 0x24, 0x74, |
- 0x00, 0x06, // RDLENGTH is 6 bytes. |
- 0xc0, 0x0c, |
- 0x00, 0x02, 0x00, 0x08 // Only A record present |
-}; |
- |
-const uint8 kSamplePacketAPrivet[] = { |
- // Header |
- 0x00, 0x00, // ID is zeroed out |
- 0x81, 0x80, // Standard query response, RA, no error |
- 0x00, 0x00, // No questions (for simplicity) |
- 0x00, 0x01, // 1 RR (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, 0x01, // TYPE is A. |
- 0x00, 0x01, // CLASS is IN. |
- 0x00, 0x00, // TTL (4 bytes) is 5 seconds |
- 0x00, 0x05, |
- 0x00, 0x04, // RDLENGTH is 4 bytes. |
- 0xc0, 0x0c, |
- 0x00, 0x02, |
-}; |
- |
-const uint8 kSamplePacketGoodbye[] = { |
- // Header |
- 0x00, 0x00, // ID is zeroed out |
- 0x81, 0x80, // Standard query response, RA, no error |
- 0x00, 0x00, // No questions (for simplicity) |
- 0x00, 0x01, // 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 zero; |
- 0x00, 0x00, |
- 0x00, 0x08, // RDLENGTH is 8 bytes. |
- 0x05, 'z', 'z', 'z', 'z', 'z', |
- 0xc0, 0x0c, |
-}; |
- |
-std::string MakeString(const uint8* data, unsigned size) { |
- return std::string(reinterpret_cast<const char*>(data), size); |
-} |
- |
-class PtrRecordCopyContainer { |
- public: |
- PtrRecordCopyContainer() {} |
- ~PtrRecordCopyContainer() {} |
- |
- bool is_set() const { return set_; } |
- |
- void SaveWithDummyArg(int unused, const RecordParsed* value) { |
- Save(value); |
- } |
- |
- void Save(const RecordParsed* value) { |
- set_ = true; |
- name_ = value->name(); |
- ptrdomain_ = value->rdata<PtrRecordRdata>()->ptrdomain(); |
- ttl_ = value->ttl(); |
- } |
- |
- bool IsRecordWith(std::string name, std::string ptrdomain) { |
- return set_ && name_ == name && ptrdomain_ == ptrdomain; |
- } |
- |
- const std::string& name() { return name_; } |
- const std::string& ptrdomain() { return ptrdomain_; } |
- int ttl() { return ttl_; } |
- |
- private: |
- bool set_; |
- std::string name_; |
- std::string ptrdomain_; |
- int ttl_; |
-}; |
- |
-class MDnsTest : public ::testing::Test { |
- public: |
- virtual void SetUp() override; |
- void DeleteTransaction(); |
- void DeleteBothListeners(); |
- void RunFor(base::TimeDelta time_period); |
- void Stop(); |
- |
- MOCK_METHOD2(MockableRecordCallback, void(MDnsTransaction::Result result, |
- const RecordParsed* record)); |
- |
- 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_; |
- IPEndPoint mdns_ipv4_endpoint_; |
- StrictMock<MockMDnsSocketFactory> socket_factory_; |
- |
- // Transactions and listeners that can be deleted by class methods for |
- // reentrancy tests. |
- scoped_ptr<MDnsTransaction> transaction_; |
- scoped_ptr<MDnsListener> listener1_; |
- scoped_ptr<MDnsListener> listener2_; |
-}; |
- |
-class MockListenerDelegate : public MDnsListener::Delegate { |
- public: |
- MOCK_METHOD2(OnRecordUpdate, |
- void(MDnsListener::UpdateType update, |
- const RecordParsed* records)); |
- MOCK_METHOD2(OnNsecRecord, void(const std::string&, unsigned)); |
- MOCK_METHOD0(OnCachePurged, void()); |
-}; |
- |
-void MDnsTest::SetUp() { |
- test_client_.StartListening(&socket_factory_); |
-} |
- |
-void MDnsTest::SimulatePacketReceive(const uint8* packet, unsigned size) { |
- socket_factory_.SimulateReceive(packet, size); |
-} |
- |
-void MDnsTest::ExpectPacket(const uint8* packet, unsigned size) { |
- EXPECT_CALL(socket_factory_, OnSendTo(MakeString(packet, size))) |
- .Times(2); |
-} |
- |
-void MDnsTest::DeleteTransaction() { |
- transaction_.reset(); |
-} |
- |
-void MDnsTest::DeleteBothListeners() { |
- listener1_.reset(); |
- listener2_.reset(); |
-} |
- |
-void MDnsTest::RunFor(base::TimeDelta time_period) { |
- base::CancelableCallback<void()> callback(base::Bind(&MDnsTest::Stop, |
- base::Unretained(this))); |
- base::MessageLoop::current()->PostDelayedTask( |
- FROM_HERE, callback.callback(), time_period); |
- |
- base::MessageLoop::current()->Run(); |
- callback.Cancel(); |
-} |
- |
-void MDnsTest::Stop() { |
- base::MessageLoop::current()->Quit(); |
-} |
- |
-TEST_F(MDnsTest, PassiveListeners) { |
- 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()); |
- |
- // Send the same packet twice to ensure no records are double-counted. |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
- .Times(Exactly(1)) |
- .WillOnce(Invoke( |
- &record_privet, |
- &PtrRecordCopyContainer::SaveWithDummyArg)); |
- |
- EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
- .Times(Exactly(1)) |
- .WillOnce(Invoke( |
- &record_printer, |
- &PtrRecordCopyContainer::SaveWithDummyArg)); |
- |
- |
- SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1)); |
- SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1)); |
- |
- EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local", |
- "hello._privet._tcp.local")); |
- |
- EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local", |
- "hello._printer._tcp.local")); |
- |
- listener_privet.reset(); |
- listener_printer.reset(); |
-} |
- |
-TEST_F(MDnsTest, PassiveListenersCacheCleanup) { |
- StrictMock<MockListenerDelegate> delegate_privet; |
- |
- PtrRecordCopyContainer record_privet; |
- PtrRecordCopyContainer record_privet2; |
- |
- scoped_ptr<MDnsListener> listener_privet = |
- test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
- &delegate_privet); |
- |
- ASSERT_TRUE(listener_privet->Start()); |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
- .Times(Exactly(1)) |
- .WillOnce(Invoke( |
- &record_privet, |
- &PtrRecordCopyContainer::SaveWithDummyArg)); |
- |
- SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1)); |
- |
- EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local", |
- "hello._privet._tcp.local")); |
- |
- // Expect record is removed when its TTL expires. |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _)) |
- .Times(Exactly(1)) |
- .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::Stop), |
- Invoke(&record_privet2, |
- &PtrRecordCopyContainer::SaveWithDummyArg))); |
- |
- RunFor(base::TimeDelta::FromSeconds(record_privet.ttl() + 1)); |
- |
- EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local", |
- "hello._privet._tcp.local")); |
-} |
- |
-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); |
- |
- ASSERT_TRUE(listener_printer->Start()); |
- |
- EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
- .Times(Exactly(1)) |
- .WillOnce(Invoke( |
- &record_printer, |
- &PtrRecordCopyContainer::SaveWithDummyArg)); |
- |
- // First, send unsalvagable packet to ensure we can deal with it. |
- SimulatePacketReceive(kCorruptedPacketUnsalvagable, |
- sizeof(kCorruptedPacketUnsalvagable)); |
- |
- // Regression test: send a packet where the question cannot be read. |
- SimulatePacketReceive(kCorruptedPacketBadQuestion, |
- sizeof(kCorruptedPacketBadQuestion)); |
- |
- // Then send salvagable packet to ensure we can extract useful records. |
- SimulatePacketReceive(kCorruptedPacketSalvagable, |
- sizeof(kCorruptedPacketSalvagable)); |
- |
- EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local", |
- "hello._printer._tcp.local")); |
-} |
- |
-TEST_F(MDnsTest, TransactionWithEmptyCache) { |
- ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
- |
- scoped_ptr<MDnsTransaction> transaction_privet = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypePTR, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- ASSERT_TRUE(transaction_privet->Start()); |
- |
- PtrRecordCopyContainer record_privet; |
- |
- EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _)) |
- .Times(Exactly(1)) |
- .WillOnce(Invoke(&record_privet, |
- &PtrRecordCopyContainer::SaveWithDummyArg)); |
- |
- SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1)); |
- |
- EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local", |
- "hello._privet._tcp.local")); |
-} |
- |
-TEST_F(MDnsTest, TransactionCacheOnlyNoResult) { |
- scoped_ptr<MDnsTransaction> transaction_privet = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypePTR, "_privet._tcp.local", |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- EXPECT_CALL(*this, |
- MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, _)) |
- .Times(Exactly(1)); |
- |
- ASSERT_TRUE(transaction_privet->Start()); |
-} |
- |
-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, |
- "codereview.chromium.local", |
- &delegate_irrelevant); |
- |
- ASSERT_TRUE(listener_irrelevant->Start()); |
- |
- SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1)); |
- |
- |
- PtrRecordCopyContainer record_privet; |
- |
- EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _)) |
- .WillOnce(Invoke(&record_privet, |
- &PtrRecordCopyContainer::SaveWithDummyArg)); |
- |
- scoped_ptr<MDnsTransaction> transaction_privet = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypePTR, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- ASSERT_TRUE(transaction_privet->Start()); |
- |
- EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local", |
- "hello._privet._tcp.local")); |
-} |
- |
-TEST_F(MDnsTest, AdditionalRecords) { |
- StrictMock<MockListenerDelegate> delegate_privet; |
- |
- PtrRecordCopyContainer record_privet; |
- |
- scoped_ptr<MDnsListener> listener_privet = |
- test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
- &delegate_privet); |
- |
- ASSERT_TRUE(listener_privet->Start()); |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
- .Times(Exactly(1)) |
- .WillOnce(Invoke( |
- &record_privet, |
- &PtrRecordCopyContainer::SaveWithDummyArg)); |
- |
- SimulatePacketReceive(kSamplePacketAdditionalOnly, |
- sizeof(kSamplePacketAdditionalOnly)); |
- |
- EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local", |
- "hello._privet._tcp.local")); |
-} |
- |
-TEST_F(MDnsTest, TransactionTimeout) { |
- ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
- |
- scoped_ptr<MDnsTransaction> transaction_privet = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypePTR, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- ASSERT_TRUE(transaction_privet->Start()); |
- |
- EXPECT_CALL(*this, |
- MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, NULL)) |
- .Times(Exactly(1)) |
- .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop)); |
- |
- RunFor(base::TimeDelta::FromSeconds(4)); |
-} |
- |
-TEST_F(MDnsTest, TransactionMultipleRecords) { |
- ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
- |
- scoped_ptr<MDnsTransaction> transaction_privet = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypePTR, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE , |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- ASSERT_TRUE(transaction_privet->Start()); |
- |
- PtrRecordCopyContainer record_privet; |
- PtrRecordCopyContainer record_privet2; |
- |
- EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _)) |
- .Times(Exactly(2)) |
- .WillOnce(Invoke(&record_privet, |
- &PtrRecordCopyContainer::SaveWithDummyArg)) |
- .WillOnce(Invoke(&record_privet2, |
- &PtrRecordCopyContainer::SaveWithDummyArg)); |
- |
- SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1)); |
- SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2)); |
- |
- EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local", |
- "hello._privet._tcp.local")); |
- |
- EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local", |
- "zzzzz._privet._tcp.local")); |
- |
- EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_DONE, NULL)) |
- .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop)); |
- |
- RunFor(base::TimeDelta::FromSeconds(4)); |
-} |
- |
-TEST_F(MDnsTest, TransactionReentrantDelete) { |
- ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
- |
- transaction_ = test_client_.CreateTransaction( |
- dns_protocol::kTypePTR, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- ASSERT_TRUE(transaction_->Start()); |
- |
- EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, |
- NULL)) |
- .Times(Exactly(1)) |
- .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction), |
- InvokeWithoutArgs(this, &MDnsTest::Stop))); |
- |
- RunFor(base::TimeDelta::FromSeconds(4)); |
- |
- EXPECT_EQ(NULL, transaction_.get()); |
-} |
- |
-TEST_F(MDnsTest, TransactionReentrantDeleteFromCache) { |
- StrictMock<MockListenerDelegate> delegate_irrelevant; |
- 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( |
- dns_protocol::kTypePTR, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _)) |
- .Times(Exactly(1)) |
- .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction)); |
- |
- ASSERT_TRUE(transaction_->Start()); |
- |
- EXPECT_EQ(NULL, transaction_.get()); |
-} |
- |
-TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) { |
- ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet)); |
- |
- scoped_ptr<MDnsTransaction> transaction1 = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypePTR, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- scoped_ptr<MDnsTransaction> transaction2 = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypePTR, "_printer._tcp.local", |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback2, |
- base::Unretained(this))); |
- |
- EXPECT_CALL(*this, MockableRecordCallback2(MDnsTransaction::RESULT_RECORD, |
- _)) |
- .Times(Exactly(1)); |
- |
- EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, |
- _)) |
- .Times(Exactly(1)) |
- .WillOnce(IgnoreResult(InvokeWithoutArgs(transaction2.get(), |
- &MDnsTransaction::Start))); |
- |
- ASSERT_TRUE(transaction1->Start()); |
- |
- SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1)); |
-} |
- |
-TEST_F(MDnsTest, GoodbyePacketNotification) { |
- StrictMock<MockListenerDelegate> delegate_privet; |
- |
- scoped_ptr<MDnsListener> listener_privet = test_client_.CreateListener( |
- dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet); |
- ASSERT_TRUE(listener_privet->Start()); |
- |
- SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye)); |
- |
- RunFor(base::TimeDelta::FromSeconds(2)); |
-} |
- |
-TEST_F(MDnsTest, GoodbyePacketRemoval) { |
- StrictMock<MockListenerDelegate> delegate_privet; |
- |
- scoped_ptr<MDnsListener> listener_privet = |
- test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local", |
- &delegate_privet); |
- ASSERT_TRUE(listener_privet->Start()); |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
- .Times(Exactly(1)); |
- |
- SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2)); |
- |
- SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye)); |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _)) |
- .Times(Exactly(1)); |
- |
- RunFor(base::TimeDelta::FromSeconds(2)); |
-} |
- |
-// In order to reliably test reentrant listener deletes, we create two listeners |
-// and have each of them delete both, so we're guaranteed to try and deliver a |
-// callback to at least one deleted listener. |
- |
-TEST_F(MDnsTest, ListenerReentrantDelete) { |
- StrictMock<MockListenerDelegate> delegate_privet; |
- |
- listener1_ = test_client_.CreateListener(dns_protocol::kTypePTR, |
- "_privet._tcp.local", |
- &delegate_privet); |
- |
- listener2_ = test_client_.CreateListener(dns_protocol::kTypePTR, |
- "_privet._tcp.local", |
- &delegate_privet); |
- |
- ASSERT_TRUE(listener1_->Start()); |
- |
- ASSERT_TRUE(listener2_->Start()); |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
- .Times(Exactly(1)) |
- .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteBothListeners)); |
- |
- SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1)); |
- |
- EXPECT_EQ(NULL, listener1_.get()); |
- EXPECT_EQ(NULL, listener2_.get()); |
-} |
- |
-ACTION_P(SaveIPAddress, ip_container) { |
- ::testing::StaticAssertTypeEq<const RecordParsed*, arg1_type>(); |
- ::testing::StaticAssertTypeEq<IPAddressNumber*, ip_container_type>(); |
- |
- *ip_container = arg1->template rdata<ARecordRdata>()->address(); |
-} |
- |
-TEST_F(MDnsTest, DoubleRecordDisagreeing) { |
- IPAddressNumber address; |
- StrictMock<MockListenerDelegate> delegate_privet; |
- |
- scoped_ptr<MDnsListener> listener_privet = |
- test_client_.CreateListener(dns_protocol::kTypeA, "privet.local", |
- &delegate_privet); |
- |
- ASSERT_TRUE(listener_privet->Start()); |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
- .Times(Exactly(1)) |
- .WillOnce(SaveIPAddress(&address)); |
- |
- SimulatePacketReceive(kCorruptedPacketDoubleRecord, |
- sizeof(kCorruptedPacketDoubleRecord)); |
- |
- EXPECT_EQ("2.3.4.5", IPAddressToString(address)); |
-} |
- |
-TEST_F(MDnsTest, NsecWithListener) { |
- StrictMock<MockListenerDelegate> delegate_privet; |
- scoped_ptr<MDnsListener> listener_privet = |
- 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", |
- &delegate_privet2); |
- |
- ASSERT_TRUE(listener_privet->Start()); |
- |
- EXPECT_CALL(delegate_privet, |
- OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA)); |
- |
- SimulatePacketReceive(kSamplePacketNsec, |
- sizeof(kSamplePacketNsec)); |
-} |
- |
-TEST_F(MDnsTest, NsecWithTransactionFromNetwork) { |
- scoped_ptr<MDnsTransaction> transaction_privet = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypeA, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2); |
- |
- ASSERT_TRUE(transaction_privet->Start()); |
- |
- EXPECT_CALL(*this, |
- MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL)); |
- |
- SimulatePacketReceive(kSamplePacketNsec, |
- sizeof(kSamplePacketNsec)); |
-} |
- |
-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", |
- &delegate_irrelevant); |
- listener_irrelevant->Start(); |
- |
- SimulatePacketReceive(kSamplePacketNsec, |
- sizeof(kSamplePacketNsec)); |
- |
- EXPECT_CALL(*this, |
- MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL)); |
- |
- scoped_ptr<MDnsTransaction> transaction_privet_a = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypeA, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- ASSERT_TRUE(transaction_privet_a->Start()); |
- |
- // Test that a PTR transaction does NOT consider the same NSEC record to be a |
- // valid answer to the query |
- |
- scoped_ptr<MDnsTransaction> transaction_privet_ptr = |
- test_client_.CreateTransaction( |
- dns_protocol::kTypePTR, "_privet._tcp.local", |
- MDnsTransaction::QUERY_NETWORK | |
- MDnsTransaction::QUERY_CACHE | |
- MDnsTransaction::SINGLE_RESULT, |
- base::Bind(&MDnsTest::MockableRecordCallback, |
- base::Unretained(this))); |
- |
- EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2); |
- |
- ASSERT_TRUE(transaction_privet_ptr->Start()); |
-} |
- |
-TEST_F(MDnsTest, NsecConflictRemoval) { |
- StrictMock<MockListenerDelegate> delegate_privet; |
- scoped_ptr<MDnsListener> listener_privet = |
- test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local", |
- &delegate_privet); |
- |
- ASSERT_TRUE(listener_privet->Start()); |
- |
- const RecordParsed* record1; |
- const RecordParsed* record2; |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)) |
- .WillOnce(SaveArg<1>(&record1)); |
- |
- SimulatePacketReceive(kSamplePacketAPrivet, |
- sizeof(kSamplePacketAPrivet)); |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _)) |
- .WillOnce(SaveArg<1>(&record2)); |
- |
- EXPECT_CALL(delegate_privet, |
- OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA)); |
- |
- SimulatePacketReceive(kSamplePacketNsec, |
- sizeof(kSamplePacketNsec)); |
- |
- EXPECT_EQ(record1, record2); |
-} |
- |
- |
-TEST_F(MDnsTest, RefreshQuery) { |
- StrictMock<MockListenerDelegate> delegate_privet; |
- scoped_ptr<MDnsListener> listener_privet = |
- test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local", |
- &delegate_privet); |
- |
- listener_privet->SetActiveRefresh(true); |
- ASSERT_TRUE(listener_privet->Start()); |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _)); |
- |
- SimulatePacketReceive(kSamplePacketAPrivet, |
- sizeof(kSamplePacketAPrivet)); |
- |
- // Expecting 2 calls (one for ipv4 and one for ipv6) for each of the 2 |
- // scheduled refresh queries. |
- EXPECT_CALL(socket_factory_, OnSendTo( |
- MakeString(kQueryPacketPrivetA, sizeof(kQueryPacketPrivetA)))) |
- .Times(4); |
- |
- EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _)); |
- |
- RunFor(base::TimeDelta::FromSeconds(6)); |
-} |
- |
-// Note: These tests assume that the ipv4 socket will always be created first. |
-// This is a simplifying assumption based on the way the code works now. |
-class SimpleMockSocketFactory : public MDnsSocketFactory { |
- public: |
- void CreateSockets(ScopedVector<DatagramServerSocket>* sockets) override { |
- sockets->clear(); |
- sockets->swap(sockets_); |
- } |
- |
- void PushSocket(DatagramServerSocket* socket) { |
- sockets_.push_back(socket); |
- } |
- |
- private: |
- ScopedVector<DatagramServerSocket> sockets_; |
-}; |
- |
-class MockMDnsConnectionDelegate : public MDnsConnection::Delegate { |
- public: |
- virtual void HandlePacket(DnsResponse* response, int size) { |
- HandlePacketInternal(std::string(response->io_buffer()->data(), size)); |
- } |
- |
- MOCK_METHOD1(HandlePacketInternal, void(std::string packet)); |
- |
- MOCK_METHOD1(OnConnectionError, void(int error)); |
-}; |
- |
-class MDnsConnectionTest : public ::testing::Test { |
- public: |
- MDnsConnectionTest() : connection_(&delegate_) { |
- } |
- |
- protected: |
- // Follow successful connection initialization. |
- virtual void SetUp() override { |
- socket_ipv4_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV4); |
- socket_ipv6_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV6); |
- factory_.PushSocket(socket_ipv6_); |
- factory_.PushSocket(socket_ipv4_); |
- sample_packet_ = MakeString(kSamplePacket1, sizeof(kSamplePacket1)); |
- sample_buffer_ = new StringIOBuffer(sample_packet_); |
- } |
- |
- bool InitConnection() { |
- return connection_.Init(&factory_); |
- } |
- |
- StrictMock<MockMDnsConnectionDelegate> delegate_; |
- |
- MockMDnsDatagramServerSocket* socket_ipv4_; |
- MockMDnsDatagramServerSocket* socket_ipv6_; |
- SimpleMockSocketFactory factory_; |
- MDnsConnection connection_; |
- TestCompletionCallback callback_; |
- std::string sample_packet_; |
- scoped_refptr<IOBuffer> sample_buffer_; |
-}; |
- |
-TEST_F(MDnsConnectionTest, ReceiveSynchronous) { |
- socket_ipv6_->SetResponsePacket(sample_packet_); |
- EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _)) |
- .WillOnce(Return(ERR_IO_PENDING)); |
- EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _)) |
- .WillOnce( |
- Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvNow)) |
- .WillOnce(Return(ERR_IO_PENDING)); |
- |
- EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_)); |
- ASSERT_TRUE(InitConnection()); |
-} |
- |
-TEST_F(MDnsConnectionTest, ReceiveAsynchronous) { |
- socket_ipv6_->SetResponsePacket(sample_packet_); |
- |
- EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _)) |
- .WillOnce(Return(ERR_IO_PENDING)); |
- EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _)) |
- .Times(2) |
- .WillOnce( |
- Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvLater)) |
- .WillOnce(Return(ERR_IO_PENDING)); |
- |
- ASSERT_TRUE(InitConnection()); |
- |
- EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_)); |
- |
- base::MessageLoop::current()->RunUntilIdle(); |
-} |
- |
-TEST_F(MDnsConnectionTest, Error) { |
- CompletionCallback callback; |
- |
- EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _)) |
- .WillOnce(Return(ERR_IO_PENDING)); |
- EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _)) |
- .WillOnce(DoAll(SaveArg<3>(&callback), Return(ERR_IO_PENDING))); |
- |
- ASSERT_TRUE(InitConnection()); |
- |
- EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED)); |
- callback.Run(ERR_SOCKET_NOT_CONNECTED); |
- base::MessageLoop::current()->RunUntilIdle(); |
-} |
- |
-class MDnsConnectionSendTest : public MDnsConnectionTest { |
- protected: |
- void SetUp() override { |
- MDnsConnectionTest::SetUp(); |
- EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _)) |
- .WillOnce(Return(ERR_IO_PENDING)); |
- EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _)) |
- .WillOnce(Return(ERR_IO_PENDING)); |
- EXPECT_TRUE(InitConnection()); |
- } |
-}; |
- |
-TEST_F(MDnsConnectionSendTest, Send) { |
- EXPECT_CALL(*socket_ipv4_, |
- SendToInternal(sample_packet_, "224.0.0.251:5353", _)); |
- EXPECT_CALL(*socket_ipv6_, |
- SendToInternal(sample_packet_, "[ff02::fb]:5353", _)); |
- |
- connection_.Send(sample_buffer_, sample_packet_.size()); |
-} |
- |
-TEST_F(MDnsConnectionSendTest, SendError) { |
- CompletionCallback callback; |
- |
- EXPECT_CALL(*socket_ipv4_, |
- SendToInternal(sample_packet_, "224.0.0.251:5353", _)); |
- EXPECT_CALL(*socket_ipv6_, |
- SendToInternal(sample_packet_, "[ff02::fb]:5353", _)) |
- .WillOnce(DoAll(SaveArg<2>(&callback), Return(ERR_SOCKET_NOT_CONNECTED))); |
- |
- connection_.Send(sample_buffer_, sample_packet_.size()); |
- EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED)); |
- base::MessageLoop::current()->RunUntilIdle(); |
-} |
- |
-TEST_F(MDnsConnectionSendTest, SendQueued) { |
- // Send data immediately. |
- EXPECT_CALL(*socket_ipv4_, |
- SendToInternal(sample_packet_, "224.0.0.251:5353", _)) |
- .Times(2) |
- .WillRepeatedly(Return(OK)); |
- |
- CompletionCallback callback; |
- // Delay sending data. Only the first call should be made. |
- EXPECT_CALL(*socket_ipv6_, |
- SendToInternal(sample_packet_, "[ff02::fb]:5353", _)) |
- .WillOnce(DoAll(SaveArg<2>(&callback), Return(ERR_IO_PENDING))); |
- |
- connection_.Send(sample_buffer_, sample_packet_.size()); |
- connection_.Send(sample_buffer_, sample_packet_.size()); |
- |
- // The second IPv6 packed is not sent yet. |
- EXPECT_CALL(*socket_ipv4_, |
- SendToInternal(sample_packet_, "224.0.0.251:5353", _)) |
- .Times(0); |
- // Expect call for the second IPv6 packed. |
- EXPECT_CALL(*socket_ipv6_, |
- SendToInternal(sample_packet_, "[ff02::fb]:5353", _)) |
- .WillOnce(Return(OK)); |
- callback.Run(OK); |
-} |
- |
-} // namespace |
- |
-} // namespace net |