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 kQueryPacketPrivetA[] = {
    245   // Header
    246   0x00, 0x00,               // ID is zeroed out
    247   0x00, 0x00,               // No flags.
    248   0x00, 0x01,               // One question.
    249   0x00, 0x00,               // 0 RRs (answers)
    250   0x00, 0x00,               // 0 authority RRs
    251   0x00, 0x00,               // 0 additional RRs
    252 
    253   // Question
    254   // This part is echoed back from the respective query.
    255   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    256   0x04, '_', 't', 'c', 'p',
    257   0x05, 'l', 'o', 'c', 'a', 'l',
    258   0x00,
    259   0x00, 0x01,        // TYPE is A.
    260   0x00, 0x01,        // CLASS is IN.
    261 };
    262 
    263 const uint8 kSamplePacketAdditionalOnly[] = {
    264   // Header
    265   0x00, 0x00,               // ID is zeroed out
    266   0x81, 0x80,               // Standard query response, RA, no error
    267   0x00, 0x00,               // No questions (for simplicity)
    268   0x00, 0x00,               // 2 RRs (answers)
    269   0x00, 0x00,               // 0 authority RRs
    270   0x00, 0x01,               // 0 additional RRs
    271 
    272   // Answer 1
    273   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    274   0x04, '_', 't', 'c', 'p',
    275   0x05, 'l', 'o', 'c', 'a', 'l',
    276   0x00,
    277   0x00, 0x0c,        // TYPE is PTR.
    278   0x00, 0x01,        // CLASS is IN.
    279   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    280   0x24, 0x74,
    281   0x00, 0x08,        // RDLENGTH is 8 bytes.
    282   0x05, 'h', 'e', 'l', 'l', 'o',
    283   0xc0, 0x0c,
    284 };
    285 
    286 const uint8 kSamplePacketNsec[] = {
    287   // Header
    288   0x00, 0x00,               // ID is zeroed out
    289   0x81, 0x80,               // Standard query response, RA, no error
    290   0x00, 0x00,               // No questions (for simplicity)
    291   0x00, 0x01,               // 1 RR (answers)
    292   0x00, 0x00,               // 0 authority RRs
    293   0x00, 0x00,               // 0 additional RRs
    294 
    295   // Answer 1
    296   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    297   0x04, '_', 't', 'c', 'p',
    298   0x05, 'l', 'o', 'c', 'a', 'l',
    299   0x00,
    300   0x00, 0x2f,        // TYPE is NSEC.
    301   0x00, 0x01,        // CLASS is IN.
    302   0x00, 0x01,        // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
    303   0x24, 0x74,
    304   0x00, 0x06,        // RDLENGTH is 6 bytes.
    305   0xc0, 0x0c,
    306   0x00, 0x02, 0x00, 0x08  // Only A record present
    307 };
    308 
    309 const uint8 kSamplePacketAPrivet[] = {
    310   // Header
    311   0x00, 0x00,               // ID is zeroed out
    312   0x81, 0x80,               // Standard query response, RA, no error
    313   0x00, 0x00,               // No questions (for simplicity)
    314   0x00, 0x01,               // 1 RR (answers)
    315   0x00, 0x00,               // 0 authority RRs
    316   0x00, 0x00,               // 0 additional RRs
    317 
    318   // Answer 1
    319   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    320   0x04, '_', 't', 'c', 'p',
    321   0x05, 'l', 'o', 'c', 'a', 'l',
    322   0x00,
    323   0x00, 0x01,        // TYPE is A.
    324   0x00, 0x01,        // CLASS is IN.
    325   0x00, 0x00,        // TTL (4 bytes) is 5 seconds
    326   0x00, 0x05,
    327   0x00, 0x04,        // RDLENGTH is 4 bytes.
    328   0xc0, 0x0c,
    329   0x00, 0x02,
    330 };
    331 
    332 const uint8 kSamplePacketGoodbye[] = {
    333   // Header
    334   0x00, 0x00,               // ID is zeroed out
    335   0x81, 0x80,               // Standard query response, RA, no error
    336   0x00, 0x00,               // No questions (for simplicity)
    337   0x00, 0x01,               // 2 RRs (answers)
    338   0x00, 0x00,               // 0 authority RRs
    339   0x00, 0x00,               // 0 additional RRs
    340 
    341   // Answer 1
    342   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
    343   0x04, '_', 't', 'c', 'p',
    344   0x05, 'l', 'o', 'c', 'a', 'l',
    345   0x00,
    346   0x00, 0x0c,        // TYPE is PTR.
    347   0x00, 0x01,        // CLASS is IN.
    348   0x00, 0x00,        // TTL (4 bytes) is zero;
    349   0x00, 0x00,
    350   0x00, 0x08,        // RDLENGTH is 8 bytes.
    351   0x05, 'z', 'z', 'z', 'z', 'z',
    352   0xc0, 0x0c,
    353 };
    354 
    355 std::string MakeString(const uint8* data, unsigned size) {
    356   return std::string(reinterpret_cast<const char*>(data), size);
    357 }
    358 
    359 class PtrRecordCopyContainer {
    360  public:
    361   PtrRecordCopyContainer() {}
    362   ~PtrRecordCopyContainer() {}
    363 
    364   bool is_set() const { return set_; }
    365 
    366   void SaveWithDummyArg(int unused, const RecordParsed* value) {
    367     Save(value);
    368   }
    369 
    370   void Save(const RecordParsed* value) {
    371     set_ = true;
    372     name_ = value->name();
    373     ptrdomain_ = value->rdata<PtrRecordRdata>()->ptrdomain();
    374     ttl_ = value->ttl();
    375   }
    376 
    377   bool IsRecordWith(std::string name, std::string ptrdomain) {
    378     return set_ && name_ == name && ptrdomain_ == ptrdomain;
    379   }
    380 
    381   const std::string& name() { return name_; }
    382   const std::string& ptrdomain() { return ptrdomain_; }
    383   int ttl() { return ttl_; }
    384 
    385  private:
    386   bool set_;
    387   std::string name_;
    388   std::string ptrdomain_;
    389   int ttl_;
    390 };
    391 
    392 class MDnsTest : public ::testing::Test {
    393  public:
    394   virtual void SetUp() OVERRIDE;
    395   void DeleteTransaction();
    396   void DeleteBothListeners();
    397   void RunFor(base::TimeDelta time_period);
    398   void Stop();
    399 
    400   MOCK_METHOD2(MockableRecordCallback, void(MDnsTransaction::Result result,
    401                                             const RecordParsed* record));
    402 
    403   MOCK_METHOD2(MockableRecordCallback2, void(MDnsTransaction::Result result,
    404                                              const RecordParsed* record));
    405 
    406 
    407  protected:
    408   void ExpectPacket(const uint8* packet, unsigned size);
    409   void SimulatePacketReceive(const uint8* packet, unsigned size);
    410 
    411   MDnsClientImpl test_client_;
    412   IPEndPoint mdns_ipv4_endpoint_;
    413   StrictMock<MockMDnsSocketFactory> socket_factory_;
    414 
    415   // Transactions and listeners that can be deleted by class methods for
    416   // reentrancy tests.
    417   scoped_ptr<MDnsTransaction> transaction_;
    418   scoped_ptr<MDnsListener> listener1_;
    419   scoped_ptr<MDnsListener> listener2_;
    420 };
    421 
    422 class MockListenerDelegate : public MDnsListener::Delegate {
    423  public:
    424   MOCK_METHOD2(OnRecordUpdate,
    425                void(MDnsListener::UpdateType update,
    426                     const RecordParsed* records));
    427   MOCK_METHOD2(OnNsecRecord, void(const std::string&, unsigned));
    428   MOCK_METHOD0(OnCachePurged, void());
    429 };
    430 
    431 void MDnsTest::SetUp() {
    432   test_client_.StartListening(&socket_factory_);
    433 }
    434 
    435 void MDnsTest::SimulatePacketReceive(const uint8* packet, unsigned size) {
    436   socket_factory_.SimulateReceive(packet, size);
    437 }
    438 
    439 void MDnsTest::ExpectPacket(const uint8* packet, unsigned size) {
    440   EXPECT_CALL(socket_factory_, OnSendTo(MakeString(packet, size)))
    441       .Times(2);
    442 }
    443 
    444 void MDnsTest::DeleteTransaction() {
    445   transaction_.reset();
    446 }
    447 
    448 void MDnsTest::DeleteBothListeners() {
    449   listener1_.reset();
    450   listener2_.reset();
    451 }
    452 
    453 void MDnsTest::RunFor(base::TimeDelta time_period) {
    454   base::CancelableCallback<void()> callback(base::Bind(&MDnsTest::Stop,
    455                                                        base::Unretained(this)));
    456   base::MessageLoop::current()->PostDelayedTask(
    457       FROM_HERE, callback.callback(), time_period);
    458 
    459   base::MessageLoop::current()->Run();
    460   callback.Cancel();
    461 }
    462 
    463 void MDnsTest::Stop() {
    464   base::MessageLoop::current()->Quit();
    465 }
    466 
    467 TEST_F(MDnsTest, PassiveListeners) {
    468   StrictMock<MockListenerDelegate> delegate_privet;
    469   StrictMock<MockListenerDelegate> delegate_printer;
    470 
    471   PtrRecordCopyContainer record_privet;
    472   PtrRecordCopyContainer record_printer;
    473 
    474   scoped_ptr<MDnsListener> listener_privet =
    475       test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
    476                                   &delegate_privet);
    477   scoped_ptr<MDnsListener> listener_printer =
    478       test_client_.CreateListener(dns_protocol::kTypePTR, "_printer._tcp.local",
    479                                   &delegate_printer);
    480 
    481   ASSERT_TRUE(listener_privet->Start());
    482   ASSERT_TRUE(listener_printer->Start());
    483 
    484   // Send the same packet twice to ensure no records are double-counted.
    485 
    486   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    487       .Times(Exactly(1))
    488       .WillOnce(Invoke(
    489           &record_privet,
    490           &PtrRecordCopyContainer::SaveWithDummyArg));
    491 
    492   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    493       .Times(Exactly(1))
    494       .WillOnce(Invoke(
    495           &record_printer,
    496           &PtrRecordCopyContainer::SaveWithDummyArg));
    497 
    498 
    499   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    500   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    501 
    502   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    503                                          "hello._privet._tcp.local"));
    504 
    505   EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
    506                                           "hello._printer._tcp.local"));
    507 
    508   listener_privet.reset();
    509   listener_printer.reset();
    510 }
    511 
    512 TEST_F(MDnsTest, PassiveListenersCacheCleanup) {
    513   StrictMock<MockListenerDelegate> delegate_privet;
    514 
    515   PtrRecordCopyContainer record_privet;
    516   PtrRecordCopyContainer record_privet2;
    517 
    518   scoped_ptr<MDnsListener> listener_privet =
    519       test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
    520                                   &delegate_privet);
    521 
    522   ASSERT_TRUE(listener_privet->Start());
    523 
    524   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    525       .Times(Exactly(1))
    526       .WillOnce(Invoke(
    527           &record_privet,
    528           &PtrRecordCopyContainer::SaveWithDummyArg));
    529 
    530   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    531 
    532   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    533                                          "hello._privet._tcp.local"));
    534 
    535   // Expect record is removed when its TTL expires.
    536   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
    537       .Times(Exactly(1))
    538       .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::Stop),
    539                       Invoke(&record_privet2,
    540                              &PtrRecordCopyContainer::SaveWithDummyArg)));
    541 
    542   RunFor(base::TimeDelta::FromSeconds(record_privet.ttl() + 1));
    543 
    544   EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
    545                                           "hello._privet._tcp.local"));
    546 }
    547 
    548 TEST_F(MDnsTest, MalformedPacket) {
    549   StrictMock<MockListenerDelegate> delegate_printer;
    550 
    551   PtrRecordCopyContainer record_printer;
    552 
    553   scoped_ptr<MDnsListener> listener_printer =
    554       test_client_.CreateListener(dns_protocol::kTypePTR, "_printer._tcp.local",
    555                                   &delegate_printer);
    556 
    557   ASSERT_TRUE(listener_printer->Start());
    558 
    559   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    560       .Times(Exactly(1))
    561       .WillOnce(Invoke(
    562           &record_printer,
    563           &PtrRecordCopyContainer::SaveWithDummyArg));
    564 
    565   // First, send unsalvagable packet to ensure we can deal with it.
    566   SimulatePacketReceive(kCorruptedPacketUnsalvagable,
    567                         sizeof(kCorruptedPacketUnsalvagable));
    568 
    569   // Regression test: send a packet where the question cannot be read.
    570   SimulatePacketReceive(kCorruptedPacketBadQuestion,
    571                         sizeof(kCorruptedPacketBadQuestion));
    572 
    573   // Then send salvagable packet to ensure we can extract useful records.
    574   SimulatePacketReceive(kCorruptedPacketSalvagable,
    575                         sizeof(kCorruptedPacketSalvagable));
    576 
    577   EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
    578                                           "hello._printer._tcp.local"));
    579 }
    580 
    581 TEST_F(MDnsTest, TransactionWithEmptyCache) {
    582   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    583 
    584   scoped_ptr<MDnsTransaction> transaction_privet =
    585       test_client_.CreateTransaction(
    586           dns_protocol::kTypePTR, "_privet._tcp.local",
    587           MDnsTransaction::QUERY_NETWORK |
    588           MDnsTransaction::QUERY_CACHE |
    589           MDnsTransaction::SINGLE_RESULT,
    590           base::Bind(&MDnsTest::MockableRecordCallback,
    591                      base::Unretained(this)));
    592 
    593   ASSERT_TRUE(transaction_privet->Start());
    594 
    595   PtrRecordCopyContainer record_privet;
    596 
    597   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
    598       .Times(Exactly(1))
    599       .WillOnce(Invoke(&record_privet,
    600                        &PtrRecordCopyContainer::SaveWithDummyArg));
    601 
    602   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    603 
    604   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    605                                          "hello._privet._tcp.local"));
    606 }
    607 
    608 TEST_F(MDnsTest, TransactionCacheOnlyNoResult) {
    609   scoped_ptr<MDnsTransaction> transaction_privet =
    610       test_client_.CreateTransaction(
    611           dns_protocol::kTypePTR, "_privet._tcp.local",
    612           MDnsTransaction::QUERY_CACHE |
    613           MDnsTransaction::SINGLE_RESULT,
    614           base::Bind(&MDnsTest::MockableRecordCallback,
    615                      base::Unretained(this)));
    616 
    617   EXPECT_CALL(*this,
    618               MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, _))
    619       .Times(Exactly(1));
    620 
    621   ASSERT_TRUE(transaction_privet->Start());
    622 }
    623 
    624 TEST_F(MDnsTest, TransactionWithCache) {
    625   // Listener to force the client to listen
    626   StrictMock<MockListenerDelegate> delegate_irrelevant;
    627   scoped_ptr<MDnsListener> listener_irrelevant =
    628       test_client_.CreateListener(dns_protocol::kTypeA,
    629                                   "codereview.chromium.local",
    630                                   &delegate_irrelevant);
    631 
    632   ASSERT_TRUE(listener_irrelevant->Start());
    633 
    634   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    635 
    636 
    637   PtrRecordCopyContainer record_privet;
    638 
    639   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
    640       .WillOnce(Invoke(&record_privet,
    641                        &PtrRecordCopyContainer::SaveWithDummyArg));
    642 
    643   scoped_ptr<MDnsTransaction> transaction_privet =
    644       test_client_.CreateTransaction(
    645           dns_protocol::kTypePTR, "_privet._tcp.local",
    646           MDnsTransaction::QUERY_NETWORK |
    647           MDnsTransaction::QUERY_CACHE |
    648           MDnsTransaction::SINGLE_RESULT,
    649           base::Bind(&MDnsTest::MockableRecordCallback,
    650                      base::Unretained(this)));
    651 
    652   ASSERT_TRUE(transaction_privet->Start());
    653 
    654   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    655                                          "hello._privet._tcp.local"));
    656 }
    657 
    658 TEST_F(MDnsTest, AdditionalRecords) {
    659   StrictMock<MockListenerDelegate> delegate_privet;
    660 
    661   PtrRecordCopyContainer record_privet;
    662 
    663   scoped_ptr<MDnsListener> listener_privet =
    664       test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
    665                                   &delegate_privet);
    666 
    667   ASSERT_TRUE(listener_privet->Start());
    668 
    669   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    670       .Times(Exactly(1))
    671       .WillOnce(Invoke(
    672           &record_privet,
    673           &PtrRecordCopyContainer::SaveWithDummyArg));
    674 
    675   SimulatePacketReceive(kSamplePacketAdditionalOnly,
    676                         sizeof(kSamplePacketAdditionalOnly));
    677 
    678   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    679                                          "hello._privet._tcp.local"));
    680 }
    681 
    682 TEST_F(MDnsTest, TransactionTimeout) {
    683   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    684 
    685   scoped_ptr<MDnsTransaction> transaction_privet =
    686       test_client_.CreateTransaction(
    687           dns_protocol::kTypePTR, "_privet._tcp.local",
    688           MDnsTransaction::QUERY_NETWORK |
    689           MDnsTransaction::QUERY_CACHE |
    690           MDnsTransaction::SINGLE_RESULT,
    691           base::Bind(&MDnsTest::MockableRecordCallback,
    692                      base::Unretained(this)));
    693 
    694   ASSERT_TRUE(transaction_privet->Start());
    695 
    696   EXPECT_CALL(*this,
    697               MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, NULL))
    698       .Times(Exactly(1))
    699       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
    700 
    701   RunFor(base::TimeDelta::FromSeconds(4));
    702 }
    703 
    704 TEST_F(MDnsTest, TransactionMultipleRecords) {
    705   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    706 
    707   scoped_ptr<MDnsTransaction> transaction_privet =
    708       test_client_.CreateTransaction(
    709           dns_protocol::kTypePTR, "_privet._tcp.local",
    710           MDnsTransaction::QUERY_NETWORK |
    711           MDnsTransaction::QUERY_CACHE ,
    712           base::Bind(&MDnsTest::MockableRecordCallback,
    713                      base::Unretained(this)));
    714 
    715   ASSERT_TRUE(transaction_privet->Start());
    716 
    717   PtrRecordCopyContainer record_privet;
    718   PtrRecordCopyContainer record_privet2;
    719 
    720   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
    721       .Times(Exactly(2))
    722       .WillOnce(Invoke(&record_privet,
    723                        &PtrRecordCopyContainer::SaveWithDummyArg))
    724       .WillOnce(Invoke(&record_privet2,
    725                        &PtrRecordCopyContainer::SaveWithDummyArg));
    726 
    727   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    728   SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
    729 
    730   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
    731                                          "hello._privet._tcp.local"));
    732 
    733   EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
    734                                           "zzzzz._privet._tcp.local"));
    735 
    736   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_DONE, NULL))
    737       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
    738 
    739   RunFor(base::TimeDelta::FromSeconds(4));
    740 }
    741 
    742 TEST_F(MDnsTest, TransactionReentrantDelete) {
    743   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    744 
    745   transaction_ = test_client_.CreateTransaction(
    746       dns_protocol::kTypePTR, "_privet._tcp.local",
    747       MDnsTransaction::QUERY_NETWORK |
    748       MDnsTransaction::QUERY_CACHE |
    749       MDnsTransaction::SINGLE_RESULT,
    750       base::Bind(&MDnsTest::MockableRecordCallback,
    751                  base::Unretained(this)));
    752 
    753   ASSERT_TRUE(transaction_->Start());
    754 
    755   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS,
    756                                             NULL))
    757       .Times(Exactly(1))
    758       .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction),
    759                       InvokeWithoutArgs(this, &MDnsTest::Stop)));
    760 
    761   RunFor(base::TimeDelta::FromSeconds(4));
    762 
    763   EXPECT_EQ(NULL, transaction_.get());
    764 }
    765 
    766 TEST_F(MDnsTest, TransactionReentrantDeleteFromCache) {
    767   StrictMock<MockListenerDelegate> delegate_irrelevant;
    768   scoped_ptr<MDnsListener> listener_irrelevant = test_client_.CreateListener(
    769       dns_protocol::kTypeA, "codereview.chromium.local",
    770       &delegate_irrelevant);
    771   ASSERT_TRUE(listener_irrelevant->Start());
    772 
    773   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    774 
    775   transaction_ = test_client_.CreateTransaction(
    776       dns_protocol::kTypePTR, "_privet._tcp.local",
    777       MDnsTransaction::QUERY_NETWORK |
    778       MDnsTransaction::QUERY_CACHE,
    779       base::Bind(&MDnsTest::MockableRecordCallback,
    780                  base::Unretained(this)));
    781 
    782   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
    783       .Times(Exactly(1))
    784       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction));
    785 
    786   ASSERT_TRUE(transaction_->Start());
    787 
    788   EXPECT_EQ(NULL, transaction_.get());
    789 }
    790 
    791 TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) {
    792   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
    793 
    794   scoped_ptr<MDnsTransaction> transaction1 =
    795       test_client_.CreateTransaction(
    796           dns_protocol::kTypePTR, "_privet._tcp.local",
    797           MDnsTransaction::QUERY_NETWORK |
    798           MDnsTransaction::QUERY_CACHE |
    799           MDnsTransaction::SINGLE_RESULT,
    800           base::Bind(&MDnsTest::MockableRecordCallback,
    801                      base::Unretained(this)));
    802 
    803   scoped_ptr<MDnsTransaction> transaction2 =
    804       test_client_.CreateTransaction(
    805           dns_protocol::kTypePTR, "_printer._tcp.local",
    806           MDnsTransaction::QUERY_CACHE |
    807           MDnsTransaction::SINGLE_RESULT,
    808           base::Bind(&MDnsTest::MockableRecordCallback2,
    809                      base::Unretained(this)));
    810 
    811   EXPECT_CALL(*this, MockableRecordCallback2(MDnsTransaction::RESULT_RECORD,
    812                                              _))
    813       .Times(Exactly(1));
    814 
    815   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD,
    816                                             _))
    817       .Times(Exactly(1))
    818       .WillOnce(IgnoreResult(InvokeWithoutArgs(transaction2.get(),
    819                                                &MDnsTransaction::Start)));
    820 
    821   ASSERT_TRUE(transaction1->Start());
    822 
    823   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    824 }
    825 
    826 TEST_F(MDnsTest, GoodbyePacketNotification) {
    827   StrictMock<MockListenerDelegate> delegate_privet;
    828 
    829   scoped_ptr<MDnsListener> listener_privet = test_client_.CreateListener(
    830       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
    831   ASSERT_TRUE(listener_privet->Start());
    832 
    833   SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
    834 
    835   RunFor(base::TimeDelta::FromSeconds(2));
    836 }
    837 
    838 TEST_F(MDnsTest, GoodbyePacketRemoval) {
    839   StrictMock<MockListenerDelegate> delegate_privet;
    840 
    841   scoped_ptr<MDnsListener> listener_privet =
    842       test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
    843                                   &delegate_privet);
    844   ASSERT_TRUE(listener_privet->Start());
    845 
    846   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    847       .Times(Exactly(1));
    848 
    849   SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
    850 
    851   SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
    852 
    853   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
    854       .Times(Exactly(1));
    855 
    856   RunFor(base::TimeDelta::FromSeconds(2));
    857 }
    858 
    859 // In order to reliably test reentrant listener deletes, we create two listeners
    860 // and have each of them delete both, so we're guaranteed to try and deliver a
    861 // callback to at least one deleted listener.
    862 
    863 TEST_F(MDnsTest, ListenerReentrantDelete) {
    864   StrictMock<MockListenerDelegate> delegate_privet;
    865 
    866   listener1_ = test_client_.CreateListener(dns_protocol::kTypePTR,
    867                                            "_privet._tcp.local",
    868                                            &delegate_privet);
    869 
    870   listener2_ = test_client_.CreateListener(dns_protocol::kTypePTR,
    871                                            "_privet._tcp.local",
    872                                            &delegate_privet);
    873 
    874   ASSERT_TRUE(listener1_->Start());
    875 
    876   ASSERT_TRUE(listener2_->Start());
    877 
    878   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    879       .Times(Exactly(1))
    880       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteBothListeners));
    881 
    882   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
    883 
    884   EXPECT_EQ(NULL, listener1_.get());
    885   EXPECT_EQ(NULL, listener2_.get());
    886 }
    887 
    888 ACTION_P(SaveIPAddress, ip_container) {
    889   ::testing::StaticAssertTypeEq<const RecordParsed*, arg1_type>();
    890   ::testing::StaticAssertTypeEq<IPAddressNumber*, ip_container_type>();
    891 
    892   *ip_container = arg1->template rdata<ARecordRdata>()->address();
    893 }
    894 
    895 TEST_F(MDnsTest, DoubleRecordDisagreeing) {
    896   IPAddressNumber address;
    897   StrictMock<MockListenerDelegate> delegate_privet;
    898 
    899   scoped_ptr<MDnsListener> listener_privet =
    900       test_client_.CreateListener(dns_protocol::kTypeA, "privet.local",
    901                                   &delegate_privet);
    902 
    903   ASSERT_TRUE(listener_privet->Start());
    904 
    905   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
    906       .Times(Exactly(1))
    907       .WillOnce(SaveIPAddress(&address));
    908 
    909   SimulatePacketReceive(kCorruptedPacketDoubleRecord,
    910                         sizeof(kCorruptedPacketDoubleRecord));
    911 
    912   EXPECT_EQ("2.3.4.5", IPAddressToString(address));
    913 }
    914 
    915 TEST_F(MDnsTest, NsecWithListener) {
    916   StrictMock<MockListenerDelegate> delegate_privet;
    917   scoped_ptr<MDnsListener> listener_privet =
    918       test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local",
    919                                   &delegate_privet);
    920 
    921   // Test to make sure nsec callback is NOT called for PTR
    922   // (which is marked as existing).
    923   StrictMock<MockListenerDelegate> delegate_privet2;
    924   scoped_ptr<MDnsListener> listener_privet2 =
    925       test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
    926                                   &delegate_privet2);
    927 
    928   ASSERT_TRUE(listener_privet->Start());
    929 
    930   EXPECT_CALL(delegate_privet,
    931               OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
    932 
    933   SimulatePacketReceive(kSamplePacketNsec,
    934                         sizeof(kSamplePacketNsec));
    935 }
    936 
    937 TEST_F(MDnsTest, NsecWithTransactionFromNetwork) {
    938   scoped_ptr<MDnsTransaction> transaction_privet =
    939       test_client_.CreateTransaction(
    940           dns_protocol::kTypeA, "_privet._tcp.local",
    941           MDnsTransaction::QUERY_NETWORK |
    942           MDnsTransaction::QUERY_CACHE |
    943           MDnsTransaction::SINGLE_RESULT,
    944           base::Bind(&MDnsTest::MockableRecordCallback,
    945                      base::Unretained(this)));
    946 
    947   EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
    948 
    949   ASSERT_TRUE(transaction_privet->Start());
    950 
    951   EXPECT_CALL(*this,
    952               MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL));
    953 
    954   SimulatePacketReceive(kSamplePacketNsec,
    955                         sizeof(kSamplePacketNsec));
    956 }
    957 
    958 TEST_F(MDnsTest, NsecWithTransactionFromCache) {
    959   // Force mDNS to listen.
    960   StrictMock<MockListenerDelegate> delegate_irrelevant;
    961   scoped_ptr<MDnsListener> listener_irrelevant =
    962       test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
    963                                   &delegate_irrelevant);
    964   listener_irrelevant->Start();
    965 
    966   SimulatePacketReceive(kSamplePacketNsec,
    967                         sizeof(kSamplePacketNsec));
    968 
    969   EXPECT_CALL(*this,
    970               MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL));
    971 
    972   scoped_ptr<MDnsTransaction> transaction_privet_a =
    973       test_client_.CreateTransaction(
    974           dns_protocol::kTypeA, "_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   ASSERT_TRUE(transaction_privet_a->Start());
    982 
    983   // Test that a PTR transaction does NOT consider the same NSEC record to be a
    984   // valid answer to the query
    985 
    986   scoped_ptr<MDnsTransaction> transaction_privet_ptr =
    987       test_client_.CreateTransaction(
    988           dns_protocol::kTypePTR, "_privet._tcp.local",
    989           MDnsTransaction::QUERY_NETWORK |
    990           MDnsTransaction::QUERY_CACHE |
    991           MDnsTransaction::SINGLE_RESULT,
    992           base::Bind(&MDnsTest::MockableRecordCallback,
    993                      base::Unretained(this)));
    994 
    995   EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
    996 
    997   ASSERT_TRUE(transaction_privet_ptr->Start());
    998 }
    999 
   1000 TEST_F(MDnsTest, NsecConflictRemoval) {
   1001   StrictMock<MockListenerDelegate> delegate_privet;
   1002   scoped_ptr<MDnsListener> listener_privet =
   1003       test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local",
   1004                                   &delegate_privet);
   1005 
   1006   ASSERT_TRUE(listener_privet->Start());
   1007 
   1008   const RecordParsed* record1;
   1009   const RecordParsed* record2;
   1010 
   1011   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
   1012       .WillOnce(SaveArg<1>(&record1));
   1013 
   1014   SimulatePacketReceive(kSamplePacketAPrivet,
   1015                         sizeof(kSamplePacketAPrivet));
   1016 
   1017   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
   1018       .WillOnce(SaveArg<1>(&record2));
   1019 
   1020   EXPECT_CALL(delegate_privet,
   1021               OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
   1022 
   1023   SimulatePacketReceive(kSamplePacketNsec,
   1024                         sizeof(kSamplePacketNsec));
   1025 
   1026   EXPECT_EQ(record1, record2);
   1027 }
   1028 
   1029 
   1030 TEST_F(MDnsTest, RefreshQuery) {
   1031   StrictMock<MockListenerDelegate> delegate_privet;
   1032   scoped_ptr<MDnsListener> listener_privet =
   1033       test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local",
   1034                                   &delegate_privet);
   1035 
   1036   listener_privet->SetActiveRefresh(true);
   1037   ASSERT_TRUE(listener_privet->Start());
   1038 
   1039   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _));
   1040 
   1041   SimulatePacketReceive(kSamplePacketAPrivet,
   1042                         sizeof(kSamplePacketAPrivet));
   1043 
   1044   // Expecting 2 calls (one for ipv4 and one for ipv6) for each of the 2
   1045   // scheduled refresh queries.
   1046   EXPECT_CALL(socket_factory_, OnSendTo(
   1047       MakeString(kQueryPacketPrivetA, sizeof(kQueryPacketPrivetA))))
   1048       .Times(4);
   1049 
   1050   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _));
   1051 
   1052   RunFor(base::TimeDelta::FromSeconds(6));
   1053 }
   1054 
   1055 // Note: These tests assume that the ipv4 socket will always be created first.
   1056 // This is a simplifying assumption based on the way the code works now.
   1057 class SimpleMockSocketFactory : public MDnsSocketFactory {
   1058  public:
   1059   virtual void CreateSockets(
   1060       ScopedVector<DatagramServerSocket>* sockets) OVERRIDE {
   1061     sockets->clear();
   1062     sockets->swap(sockets_);
   1063   }
   1064 
   1065   void PushSocket(DatagramServerSocket* socket) {
   1066     sockets_.push_back(socket);
   1067   }
   1068 
   1069  private:
   1070   ScopedVector<DatagramServerSocket> sockets_;
   1071 };
   1072 
   1073 class MockMDnsConnectionDelegate : public MDnsConnection::Delegate {
   1074  public:
   1075   virtual void HandlePacket(DnsResponse* response, int size) {
   1076     HandlePacketInternal(std::string(response->io_buffer()->data(), size));
   1077   }
   1078 
   1079   MOCK_METHOD1(HandlePacketInternal, void(std::string packet));
   1080 
   1081   MOCK_METHOD1(OnConnectionError, void(int error));
   1082 };
   1083 
   1084 class MDnsConnectionTest : public ::testing::Test {
   1085  public:
   1086   MDnsConnectionTest() : connection_(&delegate_) {
   1087   }
   1088 
   1089  protected:
   1090   // Follow successful connection initialization.
   1091   virtual void SetUp() OVERRIDE {
   1092     socket_ipv4_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV4);
   1093     socket_ipv6_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV6);
   1094     factory_.PushSocket(socket_ipv6_);
   1095     factory_.PushSocket(socket_ipv4_);
   1096     sample_packet_ = MakeString(kSamplePacket1, sizeof(kSamplePacket1));
   1097     sample_buffer_ = new StringIOBuffer(sample_packet_);
   1098   }
   1099 
   1100   bool InitConnection() {
   1101     return connection_.Init(&factory_);
   1102   }
   1103 
   1104   StrictMock<MockMDnsConnectionDelegate> delegate_;
   1105 
   1106   MockMDnsDatagramServerSocket* socket_ipv4_;
   1107   MockMDnsDatagramServerSocket* socket_ipv6_;
   1108   SimpleMockSocketFactory factory_;
   1109   MDnsConnection connection_;
   1110   TestCompletionCallback callback_;
   1111   std::string sample_packet_;
   1112   scoped_refptr<IOBuffer> sample_buffer_;
   1113 };
   1114 
   1115 TEST_F(MDnsConnectionTest, ReceiveSynchronous) {
   1116   socket_ipv6_->SetResponsePacket(sample_packet_);
   1117   EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
   1118       .WillOnce(Return(ERR_IO_PENDING));
   1119   EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
   1120       .WillOnce(
   1121           Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvNow))
   1122       .WillOnce(Return(ERR_IO_PENDING));
   1123 
   1124   EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_));
   1125   ASSERT_TRUE(InitConnection());
   1126 }
   1127 
   1128 TEST_F(MDnsConnectionTest, ReceiveAsynchronous) {
   1129   socket_ipv6_->SetResponsePacket(sample_packet_);
   1130 
   1131   EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
   1132       .WillOnce(Return(ERR_IO_PENDING));
   1133   EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
   1134       .Times(2)
   1135       .WillOnce(
   1136            Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvLater))
   1137       .WillOnce(Return(ERR_IO_PENDING));
   1138 
   1139   ASSERT_TRUE(InitConnection());
   1140 
   1141   EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_));
   1142 
   1143   base::MessageLoop::current()->RunUntilIdle();
   1144 }
   1145 
   1146 TEST_F(MDnsConnectionTest, Error) {
   1147   CompletionCallback callback;
   1148 
   1149   EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
   1150       .WillOnce(Return(ERR_IO_PENDING));
   1151   EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
   1152       .WillOnce(DoAll(SaveArg<3>(&callback), Return(ERR_IO_PENDING)));
   1153 
   1154   ASSERT_TRUE(InitConnection());
   1155 
   1156   EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
   1157   callback.Run(ERR_SOCKET_NOT_CONNECTED);
   1158   base::MessageLoop::current()->RunUntilIdle();
   1159 }
   1160 
   1161 class MDnsConnectionSendTest : public MDnsConnectionTest {
   1162  protected:
   1163   virtual void SetUp() OVERRIDE {
   1164     MDnsConnectionTest::SetUp();
   1165     EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
   1166         .WillOnce(Return(ERR_IO_PENDING));
   1167     EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
   1168         .WillOnce(Return(ERR_IO_PENDING));
   1169     EXPECT_TRUE(InitConnection());
   1170   }
   1171 };
   1172 
   1173 TEST_F(MDnsConnectionSendTest, Send) {
   1174   EXPECT_CALL(*socket_ipv4_,
   1175               SendToInternal(sample_packet_, "224.0.0.251:5353", _));
   1176   EXPECT_CALL(*socket_ipv6_,
   1177               SendToInternal(sample_packet_, "[ff02::fb]:5353", _));
   1178 
   1179   connection_.Send(sample_buffer_, sample_packet_.size());
   1180 }
   1181 
   1182 TEST_F(MDnsConnectionSendTest, SendError) {
   1183   CompletionCallback callback;
   1184 
   1185   EXPECT_CALL(*socket_ipv4_,
   1186               SendToInternal(sample_packet_, "224.0.0.251:5353", _));
   1187   EXPECT_CALL(*socket_ipv6_,
   1188               SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
   1189       .WillOnce(DoAll(SaveArg<2>(&callback), Return(ERR_SOCKET_NOT_CONNECTED)));
   1190 
   1191   connection_.Send(sample_buffer_, sample_packet_.size());
   1192   EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
   1193   base::MessageLoop::current()->RunUntilIdle();
   1194 }
   1195 
   1196 TEST_F(MDnsConnectionSendTest, SendQueued) {
   1197   // Send data immediately.
   1198   EXPECT_CALL(*socket_ipv4_,
   1199               SendToInternal(sample_packet_, "224.0.0.251:5353", _))
   1200       .Times(2)
   1201       .WillRepeatedly(Return(OK));
   1202 
   1203   CompletionCallback callback;
   1204   // Delay sending data. Only the first call should be made.
   1205   EXPECT_CALL(*socket_ipv6_,
   1206               SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
   1207       .WillOnce(DoAll(SaveArg<2>(&callback), Return(ERR_IO_PENDING)));
   1208 
   1209   connection_.Send(sample_buffer_, sample_packet_.size());
   1210   connection_.Send(sample_buffer_, sample_packet_.size());
   1211 
   1212   // The second IPv6 packed is not sent yet.
   1213   EXPECT_CALL(*socket_ipv4_,
   1214               SendToInternal(sample_packet_, "224.0.0.251:5353", _))
   1215       .Times(0);
   1216   // Expect call for the second IPv6 packed.
   1217   EXPECT_CALL(*socket_ipv6_,
   1218               SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
   1219       .WillOnce(Return(OK));
   1220   callback.Run(OK);
   1221 }
   1222 
   1223 }  // namespace
   1224 
   1225 }  // namespace net
   1226