Home | History | Annotate | Download | only in dns
      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
      3 // found in the LICENSE file.
      4 
      5 #include <queue>
      6 
      7 #include "base/memory/ref_counted.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "net/base/rand_callback.h"
     10 #include "net/base/test_completion_callback.h"
     11 #include "net/dns/mdns_client_impl.h"
     12 #include "net/dns/mock_mdns_socket_factory.h"
     13 #include "net/dns/record_rdata.h"
     14 #include "net/udp/udp_client_socket.h"
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 using ::testing::Invoke;
     19 using ::testing::InvokeWithoutArgs;
     20 using ::testing::StrictMock;
     21 using ::testing::NiceMock;
     22 using ::testing::Exactly;
     23 using ::testing::Return;
     24 using ::testing::SaveArg;
     25 using ::testing::_;
     26 
     27 namespace net {
     28 
     29 namespace {
     30 
     31 const uint8 kSamplePacket1[] = {
     32   // Header
     33   0x00, 0x00,               // ID is zeroed out
     34   0x81, 0x80,               // Standard query response, RA, no error
     35   0x00, 0x00,               // No questions (for simplicity)
     36   0x00, 0x02,               // 2 RRs (answers)
     37   0x00, 0x00,               // 0 authority RRs
     38   0x00, 0x00,               // 0 additional RRs
     39 
     40   // Answer 1
     41   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
     42   0x04, '_', 't', 'c', 'p',
     43   0x05, 'l', 'o', 'c', 'a', 'l',
     44   0x00,
     45   0x00, 0x0c,        // TYPE is PTR.
     46   0x00, 0x01,        // CLASS is IN.
     47   0x00, 0x00,        // TTL (4 bytes) is 1 second;
     48   0x00, 0x01,
     49   0x00, 0x08,        // RDLENGTH is 8 bytes.
     50   0x05, 'h', 'e', 'l', 'l', 'o',
     51   0xc0, 0x0c,
     52 
     53   // Answer 2
     54   0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',
     55   0xc0, 0x14,         // Pointer to "._tcp.local"
     56   0x00, 0x0c,        // TYPE is PTR.
     57   0x00, 0x01,        // CLASS is IN.
     58   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds.
     59   0x24, 0x75,
     60   0x00, 0x08,        // RDLENGTH is 8 bytes.
     61   0x05, 'h', 'e', 'l', 'l', 'o',
     62   0xc0, 0x32
     63 };
     64 
     65 const uint8 kCorruptedPacketBadQuestion[] = {
     66   // Header
     67   0x00, 0x00,               // ID is zeroed out
     68   0x81, 0x80,               // Standard query response, RA, no error
     69   0x00, 0x01,               // One question
     70   0x00, 0x02,               // 2 RRs (answers)
     71   0x00, 0x00,               // 0 authority RRs
     72   0x00, 0x00,               // 0 additional RRs
     73 
     74   // Question is corrupted and cannot be read.
     75   0x99, 'h', 'e', 'l', 'l', 'o',
     76   0x00,
     77   0x00, 0x00,
     78   0x00, 0x00,
     79 
     80   // Answer 1
     81   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
     82   0x04, '_', 't', 'c', 'p',
     83   0x05, 'l', 'o', 'c', 'a', 'l',
     84   0x00,
     85   0x00, 0x0c,        // TYPE is PTR.
     86   0x00, 0x01,        // CLASS is IN.
     87   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
     88   0x24, 0x74,
     89   0x00, 0x99,        // RDLENGTH is impossible
     90   0x05, 'h', 'e', 'l', 'l', 'o',
     91   0xc0, 0x0c,
     92 
     93   // Answer 2
     94   0x08, '_', 'p', 'r',  // Useless trailing data.
     95 };
     96 
     97 const uint8 kCorruptedPacketUnsalvagable[] = {
     98   // Header
     99   0x00, 0x00,               // ID is zeroed out
    100   0x81, 0x80,               // Standard query response, RA, no error
    101   0x00, 0x00,               // No questions (for simplicity)
    102   0x00, 0x02,               // 2 RRs (answers)
    103   0x00, 0x00,               // 0 authority RRs
    104   0x00, 0x00,               // 0 additional RRs
    105 
    106   // Answer 1
    107   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    108   0x04, '_', 't', 'c', 'p',
    109   0x05, 'l', 'o', 'c', 'a', 'l',
    110   0x00,
    111   0x00, 0x0c,        // TYPE is PTR.
    112   0x00, 0x01,        // CLASS is IN.
    113   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    114   0x24, 0x74,
    115   0x00, 0x99,        // RDLENGTH is impossible
    116   0x05, 'h', 'e', 'l', 'l', 'o',
    117   0xc0, 0x0c,
    118 
    119   // Answer 2
    120   0x08, '_', 'p', 'r',  // Useless trailing data.
    121 };
    122 
    123 const uint8 kCorruptedPacketDoubleRecord[] = {
    124   // Header
    125   0x00, 0x00,               // ID is zeroed out
    126   0x81, 0x80,               // Standard query response, RA, no error
    127   0x00, 0x00,               // No questions (for simplicity)
    128   0x00, 0x02,               // 2 RRs (answers)
    129   0x00, 0x00,               // 0 authority RRs
    130   0x00, 0x00,               // 0 additional RRs
    131 
    132   // Answer 1
    133   0x06, 'p', 'r', 'i', 'v', 'e', 't',
    134   0x05, 'l', 'o', 'c', 'a', 'l',
    135   0x00,
    136   0x00, 0x01,        // TYPE is A.
    137   0x00, 0x01,        // CLASS is IN.
    138   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    139   0x24, 0x74,
    140   0x00, 0x04,        // RDLENGTH is 4
    141   0x05, 0x03,
    142   0xc0, 0x0c,
    143 
    144   // Answer 2 -- Same key
    145   0x06, 'p', 'r', 'i', 'v', 'e', 't',
    146   0x05, 'l', 'o', 'c', 'a', 'l',
    147   0x00,
    148   0x00, 0x01,        // TYPE is A.
    149   0x00, 0x01,        // CLASS is IN.
    150   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    151   0x24, 0x74,
    152   0x00, 0x04,        // RDLENGTH is 4
    153   0x02, 0x03,
    154   0x04, 0x05,
    155 };
    156 
    157 const uint8 kCorruptedPacketSalvagable[] = {
    158   // Header
    159   0x00, 0x00,               // ID is zeroed out
    160   0x81, 0x80,               // Standard query response, RA, no error
    161   0x00, 0x00,               // No questions (for simplicity)
    162   0x00, 0x02,               // 2 RRs (answers)
    163   0x00, 0x00,               // 0 authority RRs
    164   0x00, 0x00,               // 0 additional RRs
    165 
    166   // Answer 1
    167   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    168   0x04, '_', 't', 'c', 'p',
    169   0x05, 'l', 'o', 'c', 'a', 'l',
    170   0x00,
    171   0x00, 0x0c,        // TYPE is PTR.
    172   0x00, 0x01,        // CLASS is IN.
    173   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    174   0x24, 0x74,
    175   0x00, 0x08,        // RDLENGTH is 8 bytes.
    176   0x99, 'h', 'e', 'l', 'l', 'o',   // Bad RDATA format.
    177   0xc0, 0x0c,
    178 
    179   // Answer 2
    180   0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',
    181   0xc0, 0x14,         // Pointer to "._tcp.local"
    182   0x00, 0x0c,        // TYPE is PTR.
    183   0x00, 0x01,        // CLASS is IN.
    184   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds.
    185   0x24, 0x75,
    186   0x00, 0x08,        // RDLENGTH is 8 bytes.
    187   0x05, 'h', 'e', 'l', 'l', 'o',
    188   0xc0, 0x32
    189 };
    190 
    191 const uint8 kSamplePacket2[] = {
    192   // Header
    193   0x00, 0x00,               // ID is zeroed out
    194   0x81, 0x80,               // Standard query response, RA, no error
    195   0x00, 0x00,               // No questions (for simplicity)
    196   0x00, 0x02,               // 2 RRs (answers)
    197   0x00, 0x00,               // 0 authority RRs
    198   0x00, 0x00,               // 0 additional RRs
    199 
    200   // Answer 1
    201   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    202   0x04, '_', 't', 'c', 'p',
    203   0x05, 'l', 'o', 'c', 'a', 'l',
    204   0x00,
    205   0x00, 0x0c,        // TYPE is PTR.
    206   0x00, 0x01,        // CLASS is IN.
    207   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    208   0x24, 0x74,
    209   0x00, 0x08,        // RDLENGTH is 8 bytes.
    210   0x05, 'z', 'z', 'z', 'z', 'z',
    211   0xc0, 0x0c,
    212 
    213   // Answer 2
    214   0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',
    215   0xc0, 0x14,         // Pointer to "._tcp.local"
    216   0x00, 0x0c,        // TYPE is PTR.
    217   0x00, 0x01,        // CLASS is IN.
    218   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    219   0x24, 0x74,
    220   0x00, 0x08,        // RDLENGTH is 8 bytes.
    221   0x05, 'z', 'z', 'z', 'z', 'z',
    222   0xc0, 0x32
    223 };
    224 
    225 const uint8 kQueryPacketPrivet[] = {
    226   // Header
    227   0x00, 0x00,               // ID is zeroed out
    228   0x00, 0x00,               // No flags.
    229   0x00, 0x01,               // One question.
    230   0x00, 0x00,               // 0 RRs (answers)
    231   0x00, 0x00,               // 0 authority RRs
    232   0x00, 0x00,               // 0 additional RRs
    233 
    234   // Question
    235   // This part is echoed back from the respective query.
    236   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    237   0x04, '_', 't', 'c', 'p',
    238   0x05, 'l', 'o', 'c', 'a', 'l',
    239   0x00,
    240   0x00, 0x0c,        // TYPE is PTR.
    241   0x00, 0x01,        // CLASS is IN.
    242 };
    243 
    244 const uint8 kSamplePacketAdditionalOnly[] = {
    245   // Header
    246   0x00, 0x00,               // ID is zeroed out
    247   0x81, 0x80,               // Standard query response, RA, no error
    248   0x00, 0x00,               // No questions (for simplicity)
    249   0x00, 0x00,               // 2 RRs (answers)
    250   0x00, 0x00,               // 0 authority RRs
    251   0x00, 0x01,               // 0 additional RRs
    252 
    253   // Answer 1
    254   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    255   0x04, '_', 't', 'c', 'p',
    256   0x05, 'l', 'o', 'c', 'a', 'l',
    257   0x00,
    258   0x00, 0x0c,        // TYPE is PTR.
    259   0x00, 0x01,        // CLASS is IN.
    260   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    261   0x24, 0x74,
    262   0x00, 0x08,        // RDLENGTH is 8 bytes.
    263   0x05, 'h', 'e', 'l', 'l', 'o',
    264   0xc0, 0x0c,
    265 };
    266 
    267 const uint8 kSamplePacketNsec[] = {
    268   // Header
    269   0x00, 0x00,               // ID is zeroed out
    270   0x81, 0x80,               // Standard query response, RA, no error
    271   0x00, 0x00,               // No questions (for simplicity)
    272   0x00, 0x01,               // 1 RR (answers)
    273   0x00, 0x00,               // 0 authority RRs
    274   0x00, 0x00,               // 0 additional RRs
    275 
    276   // Answer 1
    277   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    278   0x04, '_', 't', 'c', 'p',
    279   0x05, 'l', 'o', 'c', 'a', 'l',
    280   0x00,
    281   0x00, 0x2f,        // TYPE is NSEC.
    282   0x00, 0x01,        // CLASS is IN.
    283   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    284   0x24, 0x74,
    285   0x00, 0x06,        // RDLENGTH is 6 bytes.
    286   0xc0, 0x0c,
    287   0x00, 0x02, 0x00, 0x08  // Only A record present
    288 };
    289 
    290 const uint8 kSamplePacketAPrivet[] = {
    291   // Header
    292   0x00, 0x00,               // ID is zeroed out
    293   0x81, 0x80,               // Standard query response, RA, no error
    294   0x00, 0x00,               // No questions (for simplicity)
    295   0x00, 0x01,               // 1 RR (answers)
    296   0x00, 0x00,               // 0 authority RRs
    297   0x00, 0x00,               // 0 additional RRs
    298 
    299   // Answer 1
    300   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    301   0x04, '_', 't', 'c', 'p',
    302   0x05, 'l', 'o', 'c', 'a', 'l',
    303   0x00,
    304   0x00, 0x01,        // TYPE is A.
    305   0x00, 0x01,        // CLASS is IN.
    306   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    307   0x24, 0x74,
    308   0x00, 0x04,        // RDLENGTH is 4 bytes.
    309   0xc0, 0x0c,
    310   0x00, 0x02,
    311 };
    312 
    313 const uint8 kSamplePacketGoodbye[] = {
    314   // Header
    315   0x00, 0x00,               // ID is zeroed out
    316   0x81, 0x80,               // Standard query response, RA, no error
    317   0x00, 0x00,               // No questions (for simplicity)
    318   0x00, 0x01,               // 2 RRs (answers)
    319   0x00, 0x00,               // 0 authority RRs
    320   0x00, 0x00,               // 0 additional RRs
    321 
    322   // Answer 1
    323   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    324   0x04, '_', 't', 'c', 'p',
    325   0x05, 'l', 'o', 'c', 'a', 'l',
    326   0x00,
    327   0x00, 0x0c,        // TYPE is PTR.
    328   0x00, 0x01,        // CLASS is IN.
    329   0x00, 0x00,        // TTL (4 bytes) is zero;
    330   0x00, 0x00,
    331   0x00, 0x08,        // RDLENGTH is 8 bytes.
    332   0x05, 'z', 'z', 'z', 'z', 'z',
    333   0xc0, 0x0c,
    334 };
    335 
    336 std::string MakeString(const uint8* data, unsigned size) {
    337   return std::string(reinterpret_cast<const char*>(data), size);
    338 }
    339 
    340 class PtrRecordCopyContainer {
    341  public:
    342   PtrRecordCopyContainer() {}
    343   ~PtrRecordCopyContainer() {}
    344 
    345   bool is_set() const { return set_; }
    346 
    347   void SaveWithDummyArg(int unused, const RecordParsed* value) {
    348     Save(value);
    349   }
    350 
    351   void Save(const RecordParsed* value) {
    352     set_ = true;
    353     name_ = value->name();
    354     ptrdomain_ = value->rdata<PtrRecordRdata>()->ptrdomain();
    355     ttl_ = value->ttl();
    356   }
    357 
    358   bool IsRecordWith(std::string name, std::string ptrdomain) {
    359     return set_ && name_ == name && ptrdomain_ == ptrdomain;
    360   }
    361 
    362   const std::string& name() { return name_; }
    363   const std::string& ptrdomain() { return ptrdomain_; }
    364   int ttl() { return ttl_; }
    365 
    366  private:
    367   bool set_;
    368   std::string name_;
    369   std::string ptrdomain_;
    370   int ttl_;
    371 };
    372 
    373 class MDnsTest : public ::testing::Test {
    374  public:
    375   MDnsTest();
    376   virtual ~MDnsTest();
    377   virtual void SetUp() OVERRIDE;
    378   virtual void TearDown() OVERRIDE;
    379   void DeleteTransaction();
    380   void DeleteBothListeners();
    381   void RunFor(base::TimeDelta time_period);
    382   void Stop();
    383 
    384   MOCK_METHOD2(MockableRecordCallback, void(MDnsTransaction::Result result,
    385                                             const RecordParsed* record));
    386 
    387   MOCK_METHOD2(MockableRecordCallback2, void(MDnsTransaction::Result result,
    388                                              const RecordParsed* record));
    389 
    390 
    391  protected:
    392   void ExpectPacket(const uint8* packet, unsigned size);
    393   void SimulatePacketReceive(const uint8* packet, unsigned size);
    394 
    395   scoped_ptr<MDnsClientImpl> test_client_;
    396   IPEndPoint mdns_ipv4_endpoint_;
    397   StrictMock<MockMDnsSocketFactory>* socket_factory_;
    398 
    399   // Transactions and listeners that can be deleted by class methods for
    400   // reentrancy tests.
    401   scoped_ptr<MDnsTransaction> transaction_;
    402   scoped_ptr<MDnsListener> listener1_;
    403   scoped_ptr<MDnsListener> listener2_;
    404 };
    405 
    406 class MockListenerDelegate : public MDnsListener::Delegate {
    407  public:
    408   MOCK_METHOD2(OnRecordUpdate,
    409                void(MDnsListener::UpdateType update,
    410                     const RecordParsed* records));
    411   MOCK_METHOD2(OnNsecRecord, void(const std::string&, unsigned));
    412   MOCK_METHOD0(OnCachePurged, void());
    413 };
    414 
    415 MDnsTest::MDnsTest() {
    416   socket_factory_ = new StrictMock<MockMDnsSocketFactory>();
    417   test_client_.reset(new MDnsClientImpl(
    418       scoped_ptr<MDnsConnection::SocketFactory>(socket_factory_)));
    419 }
    420 
    421 MDnsTest::~MDnsTest() {
    422 }
    423 
    424 void MDnsTest::SetUp() {
    425   test_client_->StartListening();
    426 }
    427 
    428 void MDnsTest::TearDown() {
    429 }
    430 
    431 void MDnsTest::SimulatePacketReceive(const uint8* packet, unsigned size) {
    432   socket_factory_->SimulateReceive(packet, size);
    433 }
    434 
    435 void MDnsTest::ExpectPacket(const uint8* packet, unsigned size) {
    436   EXPECT_CALL(*socket_factory_, OnSendTo(MakeString(packet, size)))
    437       .Times(2);
    438 }
    439 
    440 void MDnsTest::DeleteTransaction() {
    441   transaction_.reset();
    442 }
    443 
    444 void MDnsTest::DeleteBothListeners() {
    445   listener1_.reset();
    446   listener2_.reset();
    447 }
    448 
    449 void MDnsTest::RunFor(base::TimeDelta time_period) {
    450   base::CancelableCallback<void()> callback(base::Bind(&MDnsTest::Stop,
    451                                                        base::Unretained(this)));
    452   base::MessageLoop::current()->PostDelayedTask(
    453       FROM_HERE, callback.callback(), time_period);
    454 
    455   base::MessageLoop::current()->Run();
    456   callback.Cancel();
    457 }
    458 
    459 void MDnsTest::Stop() {
    460   base::MessageLoop::current()->Quit();
    461 }
    462 
    463 TEST_F(MDnsTest, PassiveListeners) {
    464   StrictMock<MockListenerDelegate> delegate_privet;
    465   StrictMock<MockListenerDelegate> delegate_printer;
    466 
    467   PtrRecordCopyContainer record_privet;
    468   PtrRecordCopyContainer record_printer;
    469 
    470   scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
    471       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
    472   scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
    473       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
    474 
    475   ASSERT_TRUE(listener_privet->Start());
    476   ASSERT_TRUE(listener_printer->Start());
    477 
    478   // Send the same packet twice to ensure no records are double-counted.
    479 
    480   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    481       .Times(Exactly(1))
    482       .WillOnce(Invoke(
    483           &record_privet,
    484           &PtrRecordCopyContainer::SaveWithDummyArg));
    485 
    486   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    487       .Times(Exactly(1))
    488       .WillOnce(Invoke(
    489           &record_printer,
    490           &PtrRecordCopyContainer::SaveWithDummyArg));
    491 
    492 
    493   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    494   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    495 
    496   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    497                                          "hello._privet._tcp.local"));
    498 
    499   EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
    500                                           "hello._printer._tcp.local"));
    501 
    502   listener_privet.reset();
    503   listener_printer.reset();
    504 }
    505 
    506 TEST_F(MDnsTest, PassiveListenersCacheCleanup) {
    507   StrictMock<MockListenerDelegate> delegate_privet;
    508 
    509   PtrRecordCopyContainer record_privet;
    510   PtrRecordCopyContainer record_privet2;
    511 
    512   scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
    513       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
    514 
    515   ASSERT_TRUE(listener_privet->Start());
    516 
    517   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    518       .Times(Exactly(1))
    519       .WillOnce(Invoke(
    520           &record_privet,
    521           &PtrRecordCopyContainer::SaveWithDummyArg));
    522 
    523   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    524 
    525   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    526                                          "hello._privet._tcp.local"));
    527 
    528   // Expect record is removed when its TTL expires.
    529   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
    530       .Times(Exactly(1))
    531       .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::Stop),
    532                       Invoke(&record_privet2,
    533                              &PtrRecordCopyContainer::SaveWithDummyArg)));
    534 
    535   RunFor(base::TimeDelta::FromSeconds(record_privet.ttl() + 1));
    536 
    537   EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
    538                                           "hello._privet._tcp.local"));
    539 }
    540 
    541 TEST_F(MDnsTest, MalformedPacket) {
    542   StrictMock<MockListenerDelegate> delegate_printer;
    543 
    544   PtrRecordCopyContainer record_printer;
    545 
    546   scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
    547       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
    548 
    549   ASSERT_TRUE(listener_printer->Start());
    550 
    551   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    552       .Times(Exactly(1))
    553       .WillOnce(Invoke(
    554           &record_printer,
    555           &PtrRecordCopyContainer::SaveWithDummyArg));
    556 
    557   // First, send unsalvagable packet to ensure we can deal with it.
    558   SimulatePacketReceive(kCorruptedPacketUnsalvagable,
    559                         sizeof(kCorruptedPacketUnsalvagable));
    560 
    561   // Regression test: send a packet where the question cannot be read.
    562   SimulatePacketReceive(kCorruptedPacketBadQuestion,
    563                         sizeof(kCorruptedPacketBadQuestion));
    564 
    565   // Then send salvagable packet to ensure we can extract useful records.
    566   SimulatePacketReceive(kCorruptedPacketSalvagable,
    567                         sizeof(kCorruptedPacketSalvagable));
    568 
    569   EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
    570                                           "hello._printer._tcp.local"));
    571 }
    572 
    573 TEST_F(MDnsTest, TransactionWithEmptyCache) {
    574   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    575 
    576   scoped_ptr<MDnsTransaction> transaction_privet =
    577       test_client_->CreateTransaction(
    578           dns_protocol::kTypePTR, "_privet._tcp.local",
    579           MDnsTransaction::QUERY_NETWORK |
    580           MDnsTransaction::QUERY_CACHE |
    581           MDnsTransaction::SINGLE_RESULT,
    582           base::Bind(&MDnsTest::MockableRecordCallback,
    583                      base::Unretained(this)));
    584 
    585   ASSERT_TRUE(transaction_privet->Start());
    586 
    587   PtrRecordCopyContainer record_privet;
    588 
    589   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
    590       .Times(Exactly(1))
    591       .WillOnce(Invoke(&record_privet,
    592                        &PtrRecordCopyContainer::SaveWithDummyArg));
    593 
    594   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    595 
    596   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    597                                          "hello._privet._tcp.local"));
    598 }
    599 
    600 TEST_F(MDnsTest, TransactionCacheOnlyNoResult) {
    601   scoped_ptr<MDnsTransaction> transaction_privet =
    602       test_client_->CreateTransaction(
    603           dns_protocol::kTypePTR, "_privet._tcp.local",
    604           MDnsTransaction::QUERY_CACHE |
    605           MDnsTransaction::SINGLE_RESULT,
    606           base::Bind(&MDnsTest::MockableRecordCallback,
    607                      base::Unretained(this)));
    608 
    609   EXPECT_CALL(*this,
    610               MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, _))
    611       .Times(Exactly(1));
    612 
    613   ASSERT_TRUE(transaction_privet->Start());
    614 }
    615 
    616 TEST_F(MDnsTest, TransactionWithCache) {
    617   // Listener to force the client to listen
    618   StrictMock<MockListenerDelegate> delegate_irrelevant;
    619   scoped_ptr<MDnsListener> listener_irrelevant = test_client_->CreateListener(
    620       dns_protocol::kTypeA, "codereview.chromium.local",
    621       &delegate_irrelevant);
    622 
    623   ASSERT_TRUE(listener_irrelevant->Start());
    624 
    625   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    626 
    627 
    628   PtrRecordCopyContainer record_privet;
    629 
    630   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
    631       .WillOnce(Invoke(&record_privet,
    632                        &PtrRecordCopyContainer::SaveWithDummyArg));
    633 
    634   scoped_ptr<MDnsTransaction> transaction_privet =
    635       test_client_->CreateTransaction(
    636           dns_protocol::kTypePTR, "_privet._tcp.local",
    637           MDnsTransaction::QUERY_NETWORK |
    638           MDnsTransaction::QUERY_CACHE |
    639           MDnsTransaction::SINGLE_RESULT,
    640           base::Bind(&MDnsTest::MockableRecordCallback,
    641                      base::Unretained(this)));
    642 
    643   ASSERT_TRUE(transaction_privet->Start());
    644 
    645   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    646                                          "hello._privet._tcp.local"));
    647 }
    648 
    649 TEST_F(MDnsTest, AdditionalRecords) {
    650   StrictMock<MockListenerDelegate> delegate_privet;
    651 
    652   PtrRecordCopyContainer record_privet;
    653 
    654   scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
    655       dns_protocol::kTypePTR, "_privet._tcp.local",
    656       &delegate_privet);
    657 
    658   ASSERT_TRUE(listener_privet->Start());
    659 
    660   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    661       .Times(Exactly(1))
    662       .WillOnce(Invoke(
    663           &record_privet,
    664           &PtrRecordCopyContainer::SaveWithDummyArg));
    665 
    666   SimulatePacketReceive(kSamplePacketAdditionalOnly,
    667                         sizeof(kSamplePacketAdditionalOnly));
    668 
    669   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    670                                          "hello._privet._tcp.local"));
    671 }
    672 
    673 TEST_F(MDnsTest, TransactionTimeout) {
    674   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    675 
    676   scoped_ptr<MDnsTransaction> transaction_privet =
    677       test_client_->CreateTransaction(
    678           dns_protocol::kTypePTR, "_privet._tcp.local",
    679           MDnsTransaction::QUERY_NETWORK |
    680           MDnsTransaction::QUERY_CACHE |
    681           MDnsTransaction::SINGLE_RESULT,
    682           base::Bind(&MDnsTest::MockableRecordCallback,
    683                      base::Unretained(this)));
    684 
    685   ASSERT_TRUE(transaction_privet->Start());
    686 
    687   EXPECT_CALL(*this,
    688               MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, NULL))
    689       .Times(Exactly(1))
    690       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
    691 
    692   RunFor(base::TimeDelta::FromSeconds(4));
    693 }
    694 
    695 TEST_F(MDnsTest, TransactionMultipleRecords) {
    696   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    697 
    698   scoped_ptr<MDnsTransaction> transaction_privet =
    699       test_client_->CreateTransaction(
    700           dns_protocol::kTypePTR, "_privet._tcp.local",
    701           MDnsTransaction::QUERY_NETWORK |
    702           MDnsTransaction::QUERY_CACHE ,
    703           base::Bind(&MDnsTest::MockableRecordCallback,
    704                      base::Unretained(this)));
    705 
    706   ASSERT_TRUE(transaction_privet->Start());
    707 
    708   PtrRecordCopyContainer record_privet;
    709   PtrRecordCopyContainer record_privet2;
    710 
    711   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
    712       .Times(Exactly(2))
    713       .WillOnce(Invoke(&record_privet,
    714                        &PtrRecordCopyContainer::SaveWithDummyArg))
    715       .WillOnce(Invoke(&record_privet2,
    716                        &PtrRecordCopyContainer::SaveWithDummyArg));
    717 
    718   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    719   SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
    720 
    721   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    722                                          "hello._privet._tcp.local"));
    723 
    724   EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
    725                                           "zzzzz._privet._tcp.local"));
    726 
    727   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_DONE, NULL))
    728       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
    729 
    730   RunFor(base::TimeDelta::FromSeconds(4));
    731 }
    732 
    733 TEST_F(MDnsTest, TransactionReentrantDelete) {
    734   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    735 
    736   transaction_ = test_client_->CreateTransaction(
    737       dns_protocol::kTypePTR, "_privet._tcp.local",
    738       MDnsTransaction::QUERY_NETWORK |
    739       MDnsTransaction::QUERY_CACHE |
    740       MDnsTransaction::SINGLE_RESULT,
    741       base::Bind(&MDnsTest::MockableRecordCallback,
    742                  base::Unretained(this)));
    743 
    744   ASSERT_TRUE(transaction_->Start());
    745 
    746   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS,
    747                                             NULL))
    748       .Times(Exactly(1))
    749       .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction),
    750                       InvokeWithoutArgs(this, &MDnsTest::Stop)));
    751 
    752   RunFor(base::TimeDelta::FromSeconds(4));
    753 
    754   EXPECT_EQ(NULL, transaction_.get());
    755 }
    756 
    757 TEST_F(MDnsTest, TransactionReentrantDeleteFromCache) {
    758   StrictMock<MockListenerDelegate> delegate_irrelevant;
    759   scoped_ptr<MDnsListener> listener_irrelevant = test_client_->CreateListener(
    760       dns_protocol::kTypeA, "codereview.chromium.local",
    761       &delegate_irrelevant);
    762   ASSERT_TRUE(listener_irrelevant->Start());
    763 
    764   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    765 
    766   transaction_ = test_client_->CreateTransaction(
    767       dns_protocol::kTypePTR, "_privet._tcp.local",
    768       MDnsTransaction::QUERY_NETWORK |
    769       MDnsTransaction::QUERY_CACHE,
    770       base::Bind(&MDnsTest::MockableRecordCallback,
    771                  base::Unretained(this)));
    772 
    773   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
    774       .Times(Exactly(1))
    775       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction));
    776 
    777   ASSERT_TRUE(transaction_->Start());
    778 
    779   EXPECT_EQ(NULL, transaction_.get());
    780 }
    781 
    782 TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) {
    783   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    784 
    785   scoped_ptr<MDnsTransaction> transaction1 = test_client_->CreateTransaction(
    786       dns_protocol::kTypePTR, "_privet._tcp.local",
    787       MDnsTransaction::QUERY_NETWORK |
    788       MDnsTransaction::QUERY_CACHE |
    789       MDnsTransaction::SINGLE_RESULT,
    790       base::Bind(&MDnsTest::MockableRecordCallback,
    791                  base::Unretained(this)));
    792 
    793   scoped_ptr<MDnsTransaction> transaction2 = test_client_->CreateTransaction(
    794       dns_protocol::kTypePTR, "_printer._tcp.local",
    795       MDnsTransaction::QUERY_CACHE |
    796       MDnsTransaction::SINGLE_RESULT,
    797       base::Bind(&MDnsTest::MockableRecordCallback2,
    798                  base::Unretained(this)));
    799 
    800   EXPECT_CALL(*this, MockableRecordCallback2(MDnsTransaction::RESULT_RECORD,
    801                                              _))
    802       .Times(Exactly(1));
    803 
    804   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD,
    805                                             _))
    806       .Times(Exactly(1))
    807       .WillOnce(IgnoreResult(InvokeWithoutArgs(transaction2.get(),
    808                                                &MDnsTransaction::Start)));
    809 
    810   ASSERT_TRUE(transaction1->Start());
    811 
    812   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    813 }
    814 
    815 TEST_F(MDnsTest, GoodbyePacketNotification) {
    816   StrictMock<MockListenerDelegate> delegate_privet;
    817 
    818   scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
    819       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
    820   ASSERT_TRUE(listener_privet->Start());
    821 
    822   SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
    823 
    824   RunFor(base::TimeDelta::FromSeconds(2));
    825 }
    826 
    827 TEST_F(MDnsTest, GoodbyePacketRemoval) {
    828   StrictMock<MockListenerDelegate> delegate_privet;
    829 
    830   scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
    831       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
    832   ASSERT_TRUE(listener_privet->Start());
    833 
    834   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    835       .Times(Exactly(1));
    836 
    837   SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
    838 
    839   SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
    840 
    841   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
    842       .Times(Exactly(1));
    843 
    844   RunFor(base::TimeDelta::FromSeconds(2));
    845 }
    846 
    847 // In order to reliably test reentrant listener deletes, we create two listeners
    848 // and have each of them delete both, so we're guaranteed to try and deliver a
    849 // callback to at least one deleted listener.
    850 
    851 TEST_F(MDnsTest, ListenerReentrantDelete) {
    852   StrictMock<MockListenerDelegate> delegate_privet;
    853 
    854   listener1_ = test_client_->CreateListener(
    855       dns_protocol::kTypePTR, "_privet._tcp.local",
    856       &delegate_privet);
    857 
    858   listener2_ = test_client_->CreateListener(
    859       dns_protocol::kTypePTR, "_privet._tcp.local",
    860       &delegate_privet);
    861 
    862   ASSERT_TRUE(listener1_->Start());
    863 
    864   ASSERT_TRUE(listener2_->Start());
    865 
    866   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    867       .Times(Exactly(1))
    868       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteBothListeners));
    869 
    870   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    871 
    872   EXPECT_EQ(NULL, listener1_.get());
    873   EXPECT_EQ(NULL, listener2_.get());
    874 }
    875 
    876 ACTION_P(SaveIPAddress, ip_container) {
    877   ::testing::StaticAssertTypeEq<const RecordParsed*, arg1_type>();
    878   ::testing::StaticAssertTypeEq<IPAddressNumber*, ip_container_type>();
    879 
    880   *ip_container = arg1->template rdata<ARecordRdata>()->address();
    881 }
    882 
    883 TEST_F(MDnsTest, DoubleRecordDisagreeing) {
    884   IPAddressNumber address;
    885   StrictMock<MockListenerDelegate> delegate_privet;
    886 
    887   scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
    888       dns_protocol::kTypeA, "privet.local", &delegate_privet);
    889 
    890   ASSERT_TRUE(listener_privet->Start());
    891 
    892   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    893       .Times(Exactly(1))
    894       .WillOnce(SaveIPAddress(&address));
    895 
    896   SimulatePacketReceive(kCorruptedPacketDoubleRecord,
    897                         sizeof(kCorruptedPacketDoubleRecord));
    898 
    899   EXPECT_EQ("2.3.4.5", IPAddressToString(address));
    900 }
    901 
    902 TEST_F(MDnsTest, NsecWithListener) {
    903   StrictMock<MockListenerDelegate> delegate_privet;
    904   scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
    905       dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
    906 
    907   // Test to make sure nsec callback is NOT called for PTR
    908   // (which is marked as existing).
    909   StrictMock<MockListenerDelegate> delegate_privet2;
    910   scoped_ptr<MDnsListener> listener_privet2 = test_client_->CreateListener(
    911       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet2);
    912 
    913   ASSERT_TRUE(listener_privet->Start());
    914 
    915   EXPECT_CALL(delegate_privet,
    916               OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
    917 
    918   SimulatePacketReceive(kSamplePacketNsec,
    919                         sizeof(kSamplePacketNsec));
    920 }
    921 
    922 TEST_F(MDnsTest, NsecWithTransactionFromNetwork) {
    923   scoped_ptr<MDnsTransaction> transaction_privet =
    924       test_client_->CreateTransaction(
    925           dns_protocol::kTypeA, "_privet._tcp.local",
    926           MDnsTransaction::QUERY_NETWORK |
    927           MDnsTransaction::QUERY_CACHE |
    928           MDnsTransaction::SINGLE_RESULT,
    929           base::Bind(&MDnsTest::MockableRecordCallback,
    930                      base::Unretained(this)));
    931 
    932   EXPECT_CALL(*socket_factory_, OnSendTo(_))
    933       .Times(2);
    934 
    935   ASSERT_TRUE(transaction_privet->Start());
    936 
    937   EXPECT_CALL(*this,
    938               MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL));
    939 
    940   SimulatePacketReceive(kSamplePacketNsec,
    941                         sizeof(kSamplePacketNsec));
    942 }
    943 
    944 TEST_F(MDnsTest, NsecWithTransactionFromCache) {
    945   // Force mDNS to listen.
    946   StrictMock<MockListenerDelegate> delegate_irrelevant;
    947   scoped_ptr<MDnsListener> listener_irrelevant =
    948       test_client_->CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
    949                                    &delegate_irrelevant);
    950   listener_irrelevant->Start();
    951 
    952   SimulatePacketReceive(kSamplePacketNsec,
    953                         sizeof(kSamplePacketNsec));
    954 
    955   EXPECT_CALL(*this,
    956               MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL));
    957 
    958   scoped_ptr<MDnsTransaction> transaction_privet_a =
    959       test_client_->CreateTransaction(
    960           dns_protocol::kTypeA, "_privet._tcp.local",
    961           MDnsTransaction::QUERY_NETWORK |
    962           MDnsTransaction::QUERY_CACHE |
    963           MDnsTransaction::SINGLE_RESULT,
    964           base::Bind(&MDnsTest::MockableRecordCallback,
    965                      base::Unretained(this)));
    966 
    967   ASSERT_TRUE(transaction_privet_a->Start());
    968 
    969   // Test that a PTR transaction does NOT consider the same NSEC record to be a
    970   // valid answer to the query
    971 
    972   scoped_ptr<MDnsTransaction> transaction_privet_ptr =
    973       test_client_->CreateTransaction(
    974           dns_protocol::kTypePTR, "_privet._tcp.local",
    975           MDnsTransaction::QUERY_NETWORK |
    976           MDnsTransaction::QUERY_CACHE |
    977           MDnsTransaction::SINGLE_RESULT,
    978           base::Bind(&MDnsTest::MockableRecordCallback,
    979                      base::Unretained(this)));
    980 
    981   EXPECT_CALL(*socket_factory_, OnSendTo(_))
    982       .Times(2);
    983 
    984   ASSERT_TRUE(transaction_privet_ptr->Start());
    985 }
    986 
    987 TEST_F(MDnsTest, NsecConflictRemoval) {
    988   StrictMock<MockListenerDelegate> delegate_privet;
    989   scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
    990       dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
    991 
    992   ASSERT_TRUE(listener_privet->Start());
    993 
    994   const RecordParsed* record1;
    995   const RecordParsed* record2;
    996 
    997   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    998       .WillOnce(SaveArg<1>(&record1));
    999 
   1000   SimulatePacketReceive(kSamplePacketAPrivet,
   1001                         sizeof(kSamplePacketAPrivet));
   1002 
   1003   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
   1004       .WillOnce(SaveArg<1>(&record2));
   1005 
   1006   EXPECT_CALL(delegate_privet,
   1007               OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
   1008 
   1009   SimulatePacketReceive(kSamplePacketNsec,
   1010                         sizeof(kSamplePacketNsec));
   1011 
   1012   EXPECT_EQ(record1, record2);
   1013 }
   1014 
   1015 
   1016 // Note: These tests assume that the ipv4 socket will always be created first.
   1017 // This is a simplifying assumption based on the way the code works now.
   1018 
   1019 class SimpleMockSocketFactory
   1020     : public MDnsConnection::SocketFactory {
   1021  public:
   1022   SimpleMockSocketFactory() {
   1023   }
   1024   virtual ~SimpleMockSocketFactory() {
   1025   }
   1026 
   1027   virtual scoped_ptr<DatagramServerSocket> CreateSocket() OVERRIDE {
   1028     scoped_ptr<MockMDnsDatagramServerSocket> socket(
   1029         new StrictMock<MockMDnsDatagramServerSocket>);
   1030     sockets_.push(socket.get());
   1031     return socket.PassAs<DatagramServerSocket>();
   1032   }
   1033 
   1034   MockMDnsDatagramServerSocket* PopFirstSocket() {
   1035     MockMDnsDatagramServerSocket* socket = sockets_.front();
   1036     sockets_.pop();
   1037     return socket;
   1038   }
   1039 
   1040   size_t num_sockets() {
   1041     return sockets_.size();
   1042   }
   1043 
   1044  private:
   1045   std::queue<MockMDnsDatagramServerSocket*> sockets_;
   1046 };
   1047 
   1048 class MockMDnsConnectionDelegate : public MDnsConnection::Delegate {
   1049  public:
   1050   virtual void HandlePacket(DnsResponse* response, int size) {
   1051     HandlePacketInternal(std::string(response->io_buffer()->data(), size));
   1052   }
   1053 
   1054   MOCK_METHOD1(HandlePacketInternal, void(std::string packet));
   1055 
   1056   MOCK_METHOD1(OnConnectionError, void(int error));
   1057 };
   1058 
   1059 class MDnsConnectionTest : public ::testing::Test {
   1060  public:
   1061   MDnsConnectionTest() : connection_(&factory_, &delegate_) {
   1062   }
   1063 
   1064  protected:
   1065   // Follow successful connection initialization.
   1066   virtual void SetUp() OVERRIDE {
   1067     ASSERT_EQ(2u, factory_.num_sockets());
   1068 
   1069     socket_ipv4_ = factory_.PopFirstSocket();
   1070     socket_ipv6_ = factory_.PopFirstSocket();
   1071   }
   1072 
   1073   bool InitConnection() {
   1074     EXPECT_CALL(*socket_ipv4_, AllowAddressReuse());
   1075     EXPECT_CALL(*socket_ipv6_, AllowAddressReuse());
   1076 
   1077     EXPECT_CALL(*socket_ipv4_, SetMulticastLoopbackMode(false));
   1078     EXPECT_CALL(*socket_ipv6_, SetMulticastLoopbackMode(false));
   1079 
   1080     EXPECT_CALL(*socket_ipv4_, ListenInternal("0.0.0.0:5353"))
   1081         .WillOnce(Return(OK));
   1082     EXPECT_CALL(*socket_ipv6_, ListenInternal("[::]:5353"))
   1083         .WillOnce(Return(OK));
   1084 
   1085     EXPECT_CALL(*socket_ipv4_, JoinGroupInternal("224.0.0.251"))
   1086         .WillOnce(Return(OK));
   1087     EXPECT_CALL(*socket_ipv6_, JoinGroupInternal("ff02::fb"))
   1088         .WillOnce(Return(OK));
   1089 
   1090     return connection_.Init() == OK;
   1091   }
   1092 
   1093   StrictMock<MockMDnsConnectionDelegate> delegate_;
   1094 
   1095   MockMDnsDatagramServerSocket* socket_ipv4_;
   1096   MockMDnsDatagramServerSocket* socket_ipv6_;
   1097   SimpleMockSocketFactory factory_;
   1098   MDnsConnection connection_;
   1099   TestCompletionCallback callback_;
   1100 };
   1101 
   1102 TEST_F(MDnsConnectionTest, ReceiveSynchronous) {
   1103   std::string sample_packet = MakeString(kSamplePacket1,
   1104       sizeof(kSamplePacket1));
   1105 
   1106   socket_ipv6_->SetResponsePacket(sample_packet);
   1107   EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
   1108       .WillOnce(Return(ERR_IO_PENDING));
   1109   EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
   1110       .WillOnce(
   1111           Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvNow))
   1112       .WillOnce(Return(ERR_IO_PENDING));
   1113 
   1114   EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet));
   1115 
   1116   ASSERT_TRUE(InitConnection());
   1117 }
   1118 
   1119 TEST_F(MDnsConnectionTest, ReceiveAsynchronous) {
   1120   std::string sample_packet = MakeString(kSamplePacket1,
   1121       sizeof(kSamplePacket1));
   1122   socket_ipv6_->SetResponsePacket(sample_packet);
   1123   EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
   1124       .WillOnce(Return(ERR_IO_PENDING));
   1125   EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
   1126       .WillOnce(
   1127           Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvLater))
   1128       .WillOnce(Return(ERR_IO_PENDING));
   1129 
   1130   ASSERT_TRUE(InitConnection());
   1131 
   1132   EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet));
   1133 
   1134   base::MessageLoop::current()->RunUntilIdle();
   1135 }
   1136 
   1137 TEST_F(MDnsConnectionTest, Send) {
   1138   std::string sample_packet = MakeString(kSamplePacket1,
   1139       sizeof(kSamplePacket1));
   1140 
   1141   scoped_refptr<IOBufferWithSize> buf(
   1142       new IOBufferWithSize(sizeof kSamplePacket1));
   1143   memcpy(buf->data(), kSamplePacket1, sizeof(kSamplePacket1));
   1144 
   1145   EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
   1146       .WillOnce(Return(ERR_IO_PENDING));
   1147   EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
   1148       .WillOnce(Return(ERR_IO_PENDING));
   1149 
   1150   ASSERT_TRUE(InitConnection());
   1151 
   1152   EXPECT_CALL(*socket_ipv4_,
   1153               SendToInternal(sample_packet, "224.0.0.251:5353", _));
   1154   EXPECT_CALL(*socket_ipv6_,
   1155               SendToInternal(sample_packet, "[ff02::fb]:5353", _));
   1156 
   1157   connection_.Send(buf, buf->size());
   1158 }
   1159 
   1160 TEST_F(MDnsConnectionTest, Error) {
   1161   CompletionCallback callback;
   1162 
   1163   EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
   1164       .WillOnce(Return(ERR_IO_PENDING));
   1165   EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
   1166       .WillOnce(DoAll(SaveArg<3>(&callback),  Return(ERR_IO_PENDING)));
   1167 
   1168   ASSERT_TRUE(InitConnection());
   1169 
   1170   EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
   1171   callback.Run(ERR_SOCKET_NOT_CONNECTED);
   1172 }
   1173 
   1174 }  // namespace
   1175 
   1176 }  // namespace net
   1177