• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors
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 <memory>
6 #include <utility>
7 #include <vector>
8 
9 #include "base/functional/bind.h"
10 #include "base/location.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/memory/raw_ptr.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/run_loop.h"
15 #include "base/task/single_thread_task_runner.h"
16 #include "base/test/simple_test_clock.h"
17 #include "base/time/clock.h"
18 #include "base/time/default_clock.h"
19 #include "base/timer/mock_timer.h"
20 #include "base/timer/timer.h"
21 #include "net/base/address_family.h"
22 #include "net/base/completion_repeating_callback.h"
23 #include "net/base/ip_address.h"
24 #include "net/base/rand_callback.h"
25 #include "net/base/test_completion_callback.h"
26 #include "net/dns/mdns_client_impl.h"
27 #include "net/dns/mock_mdns_socket_factory.h"
28 #include "net/dns/record_rdata.h"
29 #include "net/log/net_log.h"
30 #include "net/socket/udp_client_socket.h"
31 #include "net/test/gtest_util.h"
32 #include "net/test/test_with_task_environment.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 
36 using ::testing::_;
37 using ::testing::Assign;
38 using ::testing::AtMost;
39 using ::testing::DoAll;
40 using ::testing::Exactly;
41 using ::testing::IgnoreResult;
42 using ::testing::Invoke;
43 using ::testing::InvokeWithoutArgs;
44 using ::testing::NiceMock;
45 using ::testing::Return;
46 using ::testing::SaveArg;
47 using ::testing::StrictMock;
48 
49 namespace net {
50 
51 namespace {
52 
53 const uint8_t kSamplePacket1[] = {
54     // Header
55     0x00, 0x00,  // ID is zeroed out
56     0x81, 0x80,  // Standard query response, RA, no error
57     0x00, 0x00,  // No questions (for simplicity)
58     0x00, 0x02,  // 2 RRs (answers)
59     0x00, 0x00,  // 0 authority RRs
60     0x00, 0x00,  // 0 additional RRs
61 
62     // Answer 1
63     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
64     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
65     0x00, 0x01,                                 // CLASS is IN.
66     0x00, 0x00,                                 // TTL (4 bytes) is 1 second;
67     0x00, 0x01, 0x00, 0x08,                     // RDLENGTH is 8 bytes.
68     0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x0c,
69 
70     // Answer 2
71     0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r', 0xc0,
72     0x14,        // Pointer to "._tcp.local"
73     0x00, 0x0c,  // TYPE is PTR.
74     0x00, 0x01,  // CLASS is IN.
75     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds.
76     0x24, 0x75, 0x00, 0x08,  // RDLENGTH is 8 bytes.
77     0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x32};
78 
79 const uint8_t kSamplePacket1WithCapitalization[] = {
80     // Header
81     0x00, 0x00,  // ID is zeroed out
82     0x81, 0x80,  // Standard query response, RA, no error
83     0x00, 0x00,  // No questions (for simplicity)
84     0x00, 0x02,  // 2 RRs (answers)
85     0x00, 0x00,  // 0 authority RRs
86     0x00, 0x00,  // 0 additional RRs
87 
88     // Answer 1
89     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 'T', 'C', 'P', 0x05,
90     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
91     0x00, 0x01,                                 // CLASS is IN.
92     0x00, 0x00,                                 // TTL (4 bytes) is 1 second;
93     0x00, 0x01, 0x00, 0x08,                     // RDLENGTH is 8 bytes.
94     0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x0c,
95 
96     // Answer 2
97     0x08, '_', 'P', 'r', 'i', 'n', 't', 'e', 'R', 0xc0,
98     0x14,        // Pointer to "._tcp.local"
99     0x00, 0x0c,  // TYPE is PTR.
100     0x00, 0x01,  // CLASS is IN.
101     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds.
102     0x24, 0x75, 0x00, 0x08,  // RDLENGTH is 8 bytes.
103     0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x32};
104 
105 const uint8_t kCorruptedPacketBadQuestion[] = {
106     // Header
107     0x00, 0x00,  // ID is zeroed out
108     0x81, 0x80,  // Standard query response, RA, no error
109     0x00, 0x01,  // One question
110     0x00, 0x02,  // 2 RRs (answers)
111     0x00, 0x00,  // 0 authority RRs
112     0x00, 0x00,  // 0 additional RRs
113 
114     // Question is corrupted and cannot be read.
115     0x99, 'h', 'e', 'l', 'l', 'o', 0x00, 0x00, 0x00, 0x00, 0x00,
116 
117     // Answer 1
118     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
119     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
120     0x00, 0x01,                                 // CLASS is IN.
121     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
122     0x24, 0x74, 0x00, 0x99,  // RDLENGTH is impossible
123     0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x0c,
124 
125     // Answer 2
126     0x08, '_', 'p', 'r',  // Useless trailing data.
127 };
128 
129 const uint8_t kCorruptedPacketUnsalvagable[] = {
130     // Header
131     0x00, 0x00,  // ID is zeroed out
132     0x81, 0x80,  // Standard query response, RA, no error
133     0x00, 0x00,  // No questions (for simplicity)
134     0x00, 0x02,  // 2 RRs (answers)
135     0x00, 0x00,  // 0 authority RRs
136     0x00, 0x00,  // 0 additional RRs
137 
138     // Answer 1
139     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
140     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
141     0x00, 0x01,                                 // CLASS is IN.
142     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
143     0x24, 0x74, 0x00, 0x99,  // RDLENGTH is impossible
144     0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x0c,
145 
146     // Answer 2
147     0x08, '_', 'p', 'r',  // Useless trailing data.
148 };
149 
150 const uint8_t kCorruptedPacketDoubleRecord[] = {
151     // Header
152     0x00, 0x00,  // ID is zeroed out
153     0x81, 0x80,  // Standard query response, RA, no error
154     0x00, 0x00,  // No questions (for simplicity)
155     0x00, 0x02,  // 2 RRs (answers)
156     0x00, 0x00,  // 0 authority RRs
157     0x00, 0x00,  // 0 additional RRs
158 
159     // Answer 1
160     0x06, 'p', 'r', 'i', 'v', 'e', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00,
161     0x00, 0x01,  // TYPE is A.
162     0x00, 0x01,  // CLASS is IN.
163     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
164     0x24, 0x74, 0x00, 0x04,  // RDLENGTH is 4
165     0x05, 0x03, 0xc0, 0x0c,
166 
167     // Answer 2 -- Same key
168     0x06, 'p', 'r', 'i', 'v', 'e', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00,
169     0x00, 0x01,  // TYPE is A.
170     0x00, 0x01,  // CLASS is IN.
171     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
172     0x24, 0x74, 0x00, 0x04,  // RDLENGTH is 4
173     0x02, 0x03, 0x04, 0x05,
174 };
175 
176 const uint8_t kCorruptedPacketSalvagable[] = {
177     // Header
178     0x00, 0x00,  // ID is zeroed out
179     0x81, 0x80,  // Standard query response, RA, no error
180     0x00, 0x00,  // No questions (for simplicity)
181     0x00, 0x02,  // 2 RRs (answers)
182     0x00, 0x00,  // 0 authority RRs
183     0x00, 0x00,  // 0 additional RRs
184 
185     // Answer 1
186     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
187     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
188     0x00, 0x01,                                 // CLASS is IN.
189     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
190     0x24, 0x74, 0x00, 0x08,         // RDLENGTH is 8 bytes.
191     0x99, 'h', 'e', 'l', 'l', 'o',  // Bad RDATA format.
192     0xc0, 0x0c,
193 
194     // Answer 2
195     0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r', 0xc0,
196     0x14,        // Pointer to "._tcp.local"
197     0x00, 0x0c,  // TYPE is PTR.
198     0x00, 0x01,  // CLASS is IN.
199     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds.
200     0x24, 0x75, 0x00, 0x08,  // RDLENGTH is 8 bytes.
201     0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x32};
202 
203 const uint8_t kSamplePacket2[] = {
204     // Header
205     0x00, 0x00,  // ID is zeroed out
206     0x81, 0x80,  // Standard query response, RA, no error
207     0x00, 0x00,  // No questions (for simplicity)
208     0x00, 0x02,  // 2 RRs (answers)
209     0x00, 0x00,  // 0 authority RRs
210     0x00, 0x00,  // 0 additional RRs
211 
212     // Answer 1
213     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
214     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
215     0x00, 0x01,                                 // CLASS is IN.
216     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
217     0x24, 0x74, 0x00, 0x08,  // RDLENGTH is 8 bytes.
218     0x05, 'z', 'z', 'z', 'z', 'z', 0xc0, 0x0c,
219 
220     // Answer 2
221     0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r', 0xc0,
222     0x14,        // Pointer to "._tcp.local"
223     0x00, 0x0c,  // TYPE is PTR.
224     0x00, 0x01,  // CLASS is IN.
225     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
226     0x24, 0x74, 0x00, 0x08,  // RDLENGTH is 8 bytes.
227     0x05, 'z', 'z', 'z', 'z', 'z', 0xc0, 0x32};
228 
229 const uint8_t kSamplePacket3[] = {
230     // Header
231     0x00, 0x00,  // ID is zeroed out
232     0x81, 0x80,  // Standard query response, RA, no error
233     0x00, 0x00,  // No questions (for simplicity)
234     0x00, 0x02,  // 2 RRs (answers)
235     0x00, 0x00,  // 0 authority RRs
236     0x00, 0x00,  // 0 additional RRs
237 
238     // Answer 1
239     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',  //
240     0x04, '_', 't', 'c', 'p',                 //
241     0x05, 'l', 'o', 'c', 'a', 'l',            //
242     0x00, 0x00, 0x0c,                         // TYPE is PTR.
243     0x00, 0x01,                               // CLASS is IN.
244     0x00, 0x00,                               // TTL (4 bytes) is 1 second;
245     0x00, 0x01,                               //
246     0x00, 0x08,                               // RDLENGTH is 8 bytes.
247     0x05, 'h', 'e', 'l', 'l', 'o',            //
248     0xc0, 0x0c,                               //
249 
250     // Answer 2
251     0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',  //
252     0xc0, 0x14,                                    // Pointer to "._tcp.local"
253     0x00, 0x0c,                                    // TYPE is PTR.
254     0x00, 0x01,                                    // CLASS is IN.
255     0x00, 0x00,                     // TTL (4 bytes) is 3 seconds.
256     0x00, 0x03,                     //
257     0x00, 0x08,                     // RDLENGTH is 8 bytes.
258     0x05, 'h', 'e', 'l', 'l', 'o',  //
259     0xc0, 0x32};
260 
261 const uint8_t kQueryPacketPrivet[] = {
262     // Header
263     0x00, 0x00,  // ID is zeroed out
264     0x00, 0x00,  // No flags.
265     0x00, 0x01,  // One question.
266     0x00, 0x00,  // 0 RRs (answers)
267     0x00, 0x00,  // 0 authority RRs
268     0x00, 0x00,  // 0 additional RRs
269 
270     // Question
271     // This part is echoed back from the respective query.
272     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
273     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
274     0x00, 0x01,                                 // CLASS is IN.
275 };
276 
277 const uint8_t kQueryPacketPrivetWithCapitalization[] = {
278     // Header
279     0x00, 0x00,  // ID is zeroed out
280     0x00, 0x00,  // No flags.
281     0x00, 0x01,  // One question.
282     0x00, 0x00,  // 0 RRs (answers)
283     0x00, 0x00,  // 0 authority RRs
284     0x00, 0x00,  // 0 additional RRs
285 
286     // Question
287     // This part is echoed back from the respective query.
288     0x07, '_', 'P', 'R', 'I', 'V', 'E', 'T', 0x04, '_', 't', 'c', 'p', 0x05,
289     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
290     0x00, 0x01,                                 // CLASS is IN.
291 };
292 
293 const uint8_t kQueryPacketPrivetA[] = {
294     // Header
295     0x00, 0x00,  // ID is zeroed out
296     0x00, 0x00,  // No flags.
297     0x00, 0x01,  // One question.
298     0x00, 0x00,  // 0 RRs (answers)
299     0x00, 0x00,  // 0 authority RRs
300     0x00, 0x00,  // 0 additional RRs
301 
302     // Question
303     // This part is echoed back from the respective query.
304     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
305     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x01,  // TYPE is A.
306     0x00, 0x01,                                 // CLASS is IN.
307 };
308 
309 const uint8_t kSamplePacketAdditionalOnly[] = {
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, 0x00,  // 2 RRs (answers)
315     0x00, 0x00,  // 0 authority RRs
316     0x00, 0x01,  // 0 additional RRs
317 
318     // Answer 1
319     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
320     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
321     0x00, 0x01,                                 // CLASS is IN.
322     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
323     0x24, 0x74, 0x00, 0x08,  // RDLENGTH is 8 bytes.
324     0x05, 'h', 'e', 'l', 'l', 'o', 0xc0, 0x0c,
325 };
326 
327 const uint8_t kSamplePacketNsec[] = {
328     // Header
329     0x00, 0x00,  // ID is zeroed out
330     0x81, 0x80,  // Standard query response, RA, no error
331     0x00, 0x00,  // No questions (for simplicity)
332     0x00, 0x01,  // 1 RR (answers)
333     0x00, 0x00,  // 0 authority RRs
334     0x00, 0x00,  // 0 additional RRs
335 
336     // Answer 1
337     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
338     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x2f,  // TYPE is NSEC.
339     0x00, 0x01,                                 // CLASS is IN.
340     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
341     0x24, 0x74, 0x00, 0x06,             // RDLENGTH is 6 bytes.
342     0xc0, 0x0c, 0x00, 0x02, 0x00, 0x08  // Only A record present
343 };
344 
345 const uint8_t kSamplePacketAPrivet[] = {
346     // Header
347     0x00, 0x00,  // ID is zeroed out
348     0x81, 0x80,  // Standard query response, RA, no error
349     0x00, 0x00,  // No questions (for simplicity)
350     0x00, 0x01,  // 1 RR (answers)
351     0x00, 0x00,  // 0 authority RRs
352     0x00, 0x00,  // 0 additional RRs
353 
354     // Answer 1
355     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
356     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x01,  // TYPE is A.
357     0x00, 0x01,                                 // CLASS is IN.
358     0x00, 0x00,                                 // TTL (4 bytes) is 5 seconds
359     0x00, 0x05, 0x00, 0x04,                     // RDLENGTH is 4 bytes.
360     0xc0, 0x0c, 0x00, 0x02,
361 };
362 
363 const uint8_t kSamplePacketGoodbye[] = {
364     // Header
365     0x00, 0x00,  // ID is zeroed out
366     0x81, 0x80,  // Standard query response, RA, no error
367     0x00, 0x00,  // No questions (for simplicity)
368     0x00, 0x01,  // 2 RRs (answers)
369     0x00, 0x00,  // 0 authority RRs
370     0x00, 0x00,  // 0 additional RRs
371 
372     // Answer 1
373     0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', 0x04, '_', 't', 'c', 'p', 0x05,
374     'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
375     0x00, 0x01,                                 // CLASS is IN.
376     0x00, 0x00,                                 // TTL (4 bytes) is zero;
377     0x00, 0x00, 0x00, 0x08,                     // RDLENGTH is 8 bytes.
378     0x05, 'z', 'z', 'z', 'z', 'z', 0xc0, 0x0c,
379 };
380 
MakeString(const uint8_t * data,unsigned size)381 std::string MakeString(const uint8_t* data, unsigned size) {
382   return std::string(reinterpret_cast<const char*>(data), size);
383 }
384 
385 class PtrRecordCopyContainer {
386  public:
387   PtrRecordCopyContainer() = default;
388   ~PtrRecordCopyContainer() = default;
389 
is_set() const390   bool is_set() const { return set_; }
391 
SaveWithDummyArg(int unused,const RecordParsed * value)392   void SaveWithDummyArg(int unused, const RecordParsed* value) {
393     Save(value);
394   }
395 
Save(const RecordParsed * value)396   void Save(const RecordParsed* value) {
397     set_ = true;
398     name_ = value->name();
399     ptrdomain_ = value->rdata<PtrRecordRdata>()->ptrdomain();
400     ttl_ = value->ttl();
401   }
402 
IsRecordWith(const std::string & name,const std::string & ptrdomain)403   bool IsRecordWith(const std::string& name, const std::string& ptrdomain) {
404     return set_ && name_ == name && ptrdomain_ == ptrdomain;
405   }
406 
name()407   const std::string& name() { return name_; }
ptrdomain()408   const std::string& ptrdomain() { return ptrdomain_; }
ttl()409   int ttl() { return ttl_; }
410 
411  private:
412   bool set_;
413   std::string name_;
414   std::string ptrdomain_;
415   int ttl_;
416 };
417 
418 class MockClock : public base::Clock {
419  public:
420   MockClock() = default;
421 
422   MockClock(const MockClock&) = delete;
423   MockClock& operator=(const MockClock&) = delete;
424 
425   ~MockClock() override = default;
426 
427   MOCK_CONST_METHOD0(Now, base::Time());
428 };
429 
430 class MockTimer : public base::MockOneShotTimer {
431  public:
432   MockTimer() = default;
433 
434   MockTimer(const MockTimer&) = delete;
435   MockTimer& operator=(const MockTimer&) = delete;
436 
437   ~MockTimer() override = default;
438 
Start(const base::Location & posted_from,base::TimeDelta delay,base::OnceClosure user_task)439   void Start(const base::Location& posted_from,
440              base::TimeDelta delay,
441              base::OnceClosure user_task) override {
442     StartObserver(posted_from, delay);
443     base::MockOneShotTimer::Start(posted_from, delay, std::move(user_task));
444   }
445 
446   // StartObserver is invoked when MockTimer::Start() is called.
447   // Does not replace the behavior of MockTimer::Start().
448   MOCK_METHOD2(StartObserver,
449                void(const base::Location& posted_from, base::TimeDelta delay));
450 };
451 
452 }  // namespace
453 
454 class MDnsTest : public TestWithTaskEnvironment {
455  public:
456   void SetUp() override;
457   void DeleteTransaction();
458   void DeleteBothListeners();
459   void RunFor(base::TimeDelta time_period);
460   void Stop();
461 
462   MOCK_METHOD2(MockableRecordCallback, void(MDnsTransaction::Result result,
463                                             const RecordParsed* record));
464 
465   MOCK_METHOD2(MockableRecordCallback2, void(MDnsTransaction::Result result,
466                                              const RecordParsed* record));
467 
468  protected:
469   void ExpectPacket(const uint8_t* packet, unsigned size);
470   void SimulatePacketReceive(const uint8_t* packet, unsigned size);
471 
472   std::unique_ptr<MDnsClientImpl> test_client_;
473   IPEndPoint mdns_ipv4_endpoint_;
474   StrictMock<MockMDnsSocketFactory> socket_factory_;
475 
476   // Transactions and listeners that can be deleted by class methods for
477   // reentrancy tests.
478   std::unique_ptr<MDnsTransaction> transaction_;
479   std::unique_ptr<MDnsListener> listener1_;
480   std::unique_ptr<MDnsListener> listener2_;
481 };
482 
483 class MockListenerDelegate : public MDnsListener::Delegate {
484  public:
485   MOCK_METHOD2(OnRecordUpdate,
486                void(MDnsListener::UpdateType update,
487                     const RecordParsed* records));
488   MOCK_METHOD2(OnNsecRecord, void(const std::string&, unsigned));
489   MOCK_METHOD0(OnCachePurged, void());
490 };
491 
SetUp()492 void MDnsTest::SetUp() {
493   test_client_ = std::make_unique<MDnsClientImpl>();
494   ASSERT_THAT(test_client_->StartListening(&socket_factory_), test::IsOk());
495 }
496 
SimulatePacketReceive(const uint8_t * packet,unsigned size)497 void MDnsTest::SimulatePacketReceive(const uint8_t* packet, unsigned size) {
498   socket_factory_.SimulateReceive(packet, size);
499 }
500 
ExpectPacket(const uint8_t * packet,unsigned size)501 void MDnsTest::ExpectPacket(const uint8_t* packet, unsigned size) {
502   EXPECT_CALL(socket_factory_, OnSendTo(MakeString(packet, size)))
503       .Times(2);
504 }
505 
DeleteTransaction()506 void MDnsTest::DeleteTransaction() {
507   transaction_.reset();
508 }
509 
DeleteBothListeners()510 void MDnsTest::DeleteBothListeners() {
511   listener1_.reset();
512   listener2_.reset();
513 }
514 
RunFor(base::TimeDelta time_period)515 void MDnsTest::RunFor(base::TimeDelta time_period) {
516   base::CancelableOnceCallback<void()> callback(
517       base::BindOnce(&MDnsTest::Stop, base::Unretained(this)));
518   base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
519       FROM_HERE, callback.callback(), time_period);
520 
521   base::RunLoop().Run();
522   callback.Cancel();
523 }
524 
Stop()525 void MDnsTest::Stop() {
526   base::RunLoop::QuitCurrentWhenIdleDeprecated();
527 }
528 
TEST_F(MDnsTest,PassiveListeners)529 TEST_F(MDnsTest, PassiveListeners) {
530   StrictMock<MockListenerDelegate> delegate_privet;
531   StrictMock<MockListenerDelegate> delegate_printer;
532 
533   PtrRecordCopyContainer record_privet;
534   PtrRecordCopyContainer record_printer;
535 
536   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
537       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
538   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
539       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
540 
541   ASSERT_TRUE(listener_privet->Start());
542   ASSERT_TRUE(listener_printer->Start());
543 
544   // Send the same packet twice to ensure no records are double-counted.
545 
546   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
547       .Times(Exactly(1))
548       .WillOnce(Invoke(
549           &record_privet,
550           &PtrRecordCopyContainer::SaveWithDummyArg));
551 
552   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
553       .Times(Exactly(1))
554       .WillOnce(Invoke(
555           &record_printer,
556           &PtrRecordCopyContainer::SaveWithDummyArg));
557 
558 
559   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
560   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
561 
562   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
563                                          "hello._privet._tcp.local"));
564 
565   EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
566                                           "hello._printer._tcp.local"));
567 
568   listener_privet.reset();
569   listener_printer.reset();
570 }
571 
TEST_F(MDnsTest,PassiveListenersWithCapitalization)572 TEST_F(MDnsTest, PassiveListenersWithCapitalization) {
573   StrictMock<MockListenerDelegate> delegate_privet;
574   StrictMock<MockListenerDelegate> delegate_printer;
575 
576   PtrRecordCopyContainer record_privet;
577   PtrRecordCopyContainer record_printer;
578 
579   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
580       dns_protocol::kTypePTR, "_privet._tcp.LOCAL", &delegate_privet);
581   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
582       dns_protocol::kTypePTR, "_prinTER._Tcp.Local", &delegate_printer);
583 
584   ASSERT_TRUE(listener_privet->Start());
585   ASSERT_TRUE(listener_printer->Start());
586 
587   // Send the same packet twice to ensure no records are double-counted.
588 
589   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
590       .Times(Exactly(1))
591       .WillOnce(
592           Invoke(&record_privet, &PtrRecordCopyContainer::SaveWithDummyArg));
593 
594   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
595       .Times(Exactly(1))
596       .WillOnce(
597           Invoke(&record_printer, &PtrRecordCopyContainer::SaveWithDummyArg));
598 
599   SimulatePacketReceive(kSamplePacket1WithCapitalization,
600                         sizeof(kSamplePacket1WithCapitalization));
601   SimulatePacketReceive(kSamplePacket1WithCapitalization,
602                         sizeof(kSamplePacket1WithCapitalization));
603 
604   EXPECT_TRUE(record_privet.IsRecordWith("_privet._TCP.local",
605                                          "hello._privet._TCP.local"));
606 
607   EXPECT_TRUE(record_printer.IsRecordWith("_PrinteR._TCP.local",
608                                           "hello._PrinteR._TCP.local"));
609 
610   listener_privet.reset();
611   listener_printer.reset();
612 }
613 
TEST_F(MDnsTest,PassiveListenersCacheCleanup)614 TEST_F(MDnsTest, PassiveListenersCacheCleanup) {
615   StrictMock<MockListenerDelegate> delegate_privet;
616 
617   PtrRecordCopyContainer record_privet;
618   PtrRecordCopyContainer record_privet2;
619 
620   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
621       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
622 
623   ASSERT_TRUE(listener_privet->Start());
624 
625   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
626       .Times(Exactly(1))
627       .WillOnce(Invoke(
628           &record_privet,
629           &PtrRecordCopyContainer::SaveWithDummyArg));
630 
631   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
632 
633   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
634                                          "hello._privet._tcp.local"));
635 
636   // Expect record is removed when its TTL expires.
637   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
638       .Times(Exactly(1))
639       .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::Stop),
640                       Invoke(&record_privet2,
641                              &PtrRecordCopyContainer::SaveWithDummyArg)));
642 
643   RunFor(base::Seconds(record_privet.ttl() + 1));
644 
645   EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
646                                           "hello._privet._tcp.local"));
647 }
648 
649 // Ensure that the cleanup task scheduler won't schedule cleanup tasks in the
650 // past if the system clock creeps past the expiration time while in the
651 // cleanup dispatcher.
TEST_F(MDnsTest,CacheCleanupWithShortTTL)652 TEST_F(MDnsTest, CacheCleanupWithShortTTL) {
653   // Use a nonzero starting time as a base.
654   base::Time start_time = base::Time() + base::Seconds(1);
655 
656   MockClock clock;
657   auto timer = std::make_unique<MockTimer>();
658   MockTimer* timer_ptr = timer.get();
659 
660   test_client_ = std::make_unique<MDnsClientImpl>(&clock, std::move(timer));
661   ASSERT_THAT(test_client_->StartListening(&socket_factory_), test::IsOk());
662 
663   EXPECT_CALL(*timer_ptr, StartObserver(_, _)).Times(1);
664   EXPECT_CALL(clock, Now())
665       .Times(3)
666       .WillRepeatedly(Return(start_time))
667       .RetiresOnSaturation();
668 
669   // Receive two records with different TTL values.
670   // TTL(privet)=1.0s
671   // TTL(printer)=3.0s
672   StrictMock<MockListenerDelegate> delegate_privet;
673   StrictMock<MockListenerDelegate> delegate_printer;
674 
675   PtrRecordCopyContainer record_privet;
676   PtrRecordCopyContainer record_printer;
677 
678   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
679       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
680   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
681       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
682 
683   ASSERT_TRUE(listener_privet->Start());
684   ASSERT_TRUE(listener_printer->Start());
685 
686   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
687       .Times(Exactly(1));
688   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
689       .Times(Exactly(1));
690 
691   SimulatePacketReceive(kSamplePacket3, sizeof(kSamplePacket3));
692 
693   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
694       .Times(Exactly(1));
695 
696   // Set the clock to 2.0s, which should clean up the 'privet' record, but not
697   // the printer. The mock clock will change Now() mid-execution from 2s to 4s.
698   // Note: expectations are FILO-ordered -- t+2 seconds is returned, then t+4.
699   EXPECT_CALL(clock, Now())
700       .WillOnce(Return(start_time + base::Seconds(4)))
701       .RetiresOnSaturation();
702   EXPECT_CALL(clock, Now())
703       .WillOnce(Return(start_time + base::Seconds(2)))
704       .RetiresOnSaturation();
705 
706   EXPECT_CALL(*timer_ptr, StartObserver(_, base::TimeDelta()));
707 
708   timer_ptr->Fire();
709 }
710 
TEST_F(MDnsTest,StopListening)711 TEST_F(MDnsTest, StopListening) {
712   ASSERT_TRUE(test_client_->IsListening());
713 
714   test_client_->StopListening();
715   EXPECT_FALSE(test_client_->IsListening());
716 }
717 
TEST_F(MDnsTest,StopListening_CacheCleanupScheduled)718 TEST_F(MDnsTest, StopListening_CacheCleanupScheduled) {
719   base::SimpleTestClock clock;
720   // Use a nonzero starting time as a base.
721   clock.SetNow(base::Time() + base::Seconds(1));
722   auto cleanup_timer = std::make_unique<base::MockOneShotTimer>();
723   base::OneShotTimer* cleanup_timer_ptr = cleanup_timer.get();
724 
725   test_client_ =
726       std::make_unique<MDnsClientImpl>(&clock, std::move(cleanup_timer));
727   ASSERT_THAT(test_client_->StartListening(&socket_factory_), test::IsOk());
728   ASSERT_TRUE(test_client_->IsListening());
729 
730   // Receive one record (privet) with TTL=1s to schedule cleanup.
731   SimulatePacketReceive(kSamplePacket3, sizeof(kSamplePacket3));
732   ASSERT_TRUE(cleanup_timer_ptr->IsRunning());
733 
734   test_client_->StopListening();
735   EXPECT_FALSE(test_client_->IsListening());
736 
737   // Expect cleanup unscheduled.
738   EXPECT_FALSE(cleanup_timer_ptr->IsRunning());
739 }
740 
TEST_F(MDnsTest,MalformedPacket)741 TEST_F(MDnsTest, MalformedPacket) {
742   StrictMock<MockListenerDelegate> delegate_printer;
743 
744   PtrRecordCopyContainer record_printer;
745 
746   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
747       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
748 
749   ASSERT_TRUE(listener_printer->Start());
750 
751   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
752       .Times(Exactly(1))
753       .WillOnce(Invoke(
754           &record_printer,
755           &PtrRecordCopyContainer::SaveWithDummyArg));
756 
757   // First, send unsalvagable packet to ensure we can deal with it.
758   SimulatePacketReceive(kCorruptedPacketUnsalvagable,
759                         sizeof(kCorruptedPacketUnsalvagable));
760 
761   // Regression test: send a packet where the question cannot be read.
762   SimulatePacketReceive(kCorruptedPacketBadQuestion,
763                         sizeof(kCorruptedPacketBadQuestion));
764 
765   // Then send salvagable packet to ensure we can extract useful records.
766   SimulatePacketReceive(kCorruptedPacketSalvagable,
767                         sizeof(kCorruptedPacketSalvagable));
768 
769   EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
770                                           "hello._printer._tcp.local"));
771 }
772 
TEST_F(MDnsTest,TransactionWithEmptyCache)773 TEST_F(MDnsTest, TransactionWithEmptyCache) {
774   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
775 
776   std::unique_ptr<MDnsTransaction> transaction_privet =
777       test_client_->CreateTransaction(
778           dns_protocol::kTypePTR, "_privet._tcp.local",
779           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
780               MDnsTransaction::SINGLE_RESULT,
781           base::BindRepeating(&MDnsTest::MockableRecordCallback,
782                               base::Unretained(this)));
783 
784   ASSERT_TRUE(transaction_privet->Start());
785 
786   PtrRecordCopyContainer record_privet;
787 
788   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
789       .Times(Exactly(1))
790       .WillOnce(Invoke(&record_privet,
791                        &PtrRecordCopyContainer::SaveWithDummyArg));
792 
793   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
794 
795   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
796                                          "hello._privet._tcp.local"));
797 }
798 
TEST_F(MDnsTest,TransactionWithEmptyCacheAndCapitalization)799 TEST_F(MDnsTest, TransactionWithEmptyCacheAndCapitalization) {
800   ExpectPacket(kQueryPacketPrivetWithCapitalization,
801                sizeof(kQueryPacketPrivetWithCapitalization));
802 
803   std::unique_ptr<MDnsTransaction> transaction_privet =
804       test_client_->CreateTransaction(
805           dns_protocol::kTypePTR, "_PRIVET._tcp.local",
806           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
807               MDnsTransaction::SINGLE_RESULT,
808           base::BindRepeating(&MDnsTest::MockableRecordCallback,
809                               base::Unretained(this)));
810 
811   ASSERT_TRUE(transaction_privet->Start());
812 
813   PtrRecordCopyContainer record_privet;
814 
815   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
816       .Times(Exactly(1))
817       .WillOnce(
818           Invoke(&record_privet, &PtrRecordCopyContainer::SaveWithDummyArg));
819 
820   SimulatePacketReceive(kSamplePacket1WithCapitalization,
821                         sizeof(kSamplePacket1WithCapitalization));
822 
823   EXPECT_TRUE(record_privet.IsRecordWith("_privet._TCP.local",
824                                          "hello._privet._TCP.local"));
825 }
826 
TEST_F(MDnsTest,TransactionCacheOnlyNoResult)827 TEST_F(MDnsTest, TransactionCacheOnlyNoResult) {
828   std::unique_ptr<MDnsTransaction> transaction_privet =
829       test_client_->CreateTransaction(
830           dns_protocol::kTypePTR, "_privet._tcp.local",
831           MDnsTransaction::QUERY_CACHE | MDnsTransaction::SINGLE_RESULT,
832           base::BindRepeating(&MDnsTest::MockableRecordCallback,
833                               base::Unretained(this)));
834 
835   EXPECT_CALL(*this,
836               MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, _))
837       .Times(Exactly(1));
838 
839   ASSERT_TRUE(transaction_privet->Start());
840 }
841 
TEST_F(MDnsTest,TransactionWithCache)842 TEST_F(MDnsTest, TransactionWithCache) {
843   // Listener to force the client to listen
844   StrictMock<MockListenerDelegate> delegate_irrelevant;
845   std::unique_ptr<MDnsListener> listener_irrelevant =
846       test_client_->CreateListener(dns_protocol::kTypeA,
847                                    "codereview.chromium.local",
848                                    &delegate_irrelevant);
849 
850   ASSERT_TRUE(listener_irrelevant->Start());
851 
852   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
853 
854 
855   PtrRecordCopyContainer record_privet;
856 
857   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
858       .WillOnce(Invoke(&record_privet,
859                        &PtrRecordCopyContainer::SaveWithDummyArg));
860 
861   std::unique_ptr<MDnsTransaction> transaction_privet =
862       test_client_->CreateTransaction(
863           dns_protocol::kTypePTR, "_privet._tcp.local",
864           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
865               MDnsTransaction::SINGLE_RESULT,
866           base::BindRepeating(&MDnsTest::MockableRecordCallback,
867                               base::Unretained(this)));
868 
869   ASSERT_TRUE(transaction_privet->Start());
870 
871   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
872                                          "hello._privet._tcp.local"));
873 }
874 
TEST_F(MDnsTest,AdditionalRecords)875 TEST_F(MDnsTest, AdditionalRecords) {
876   StrictMock<MockListenerDelegate> delegate_privet;
877 
878   PtrRecordCopyContainer record_privet;
879 
880   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
881       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
882 
883   ASSERT_TRUE(listener_privet->Start());
884 
885   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
886       .Times(Exactly(1))
887       .WillOnce(Invoke(
888           &record_privet,
889           &PtrRecordCopyContainer::SaveWithDummyArg));
890 
891   SimulatePacketReceive(kSamplePacketAdditionalOnly,
892                         sizeof(kSamplePacketAdditionalOnly));
893 
894   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
895                                          "hello._privet._tcp.local"));
896 }
897 
TEST_F(MDnsTest,TransactionTimeout)898 TEST_F(MDnsTest, TransactionTimeout) {
899   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
900 
901   std::unique_ptr<MDnsTransaction> transaction_privet =
902       test_client_->CreateTransaction(
903           dns_protocol::kTypePTR, "_privet._tcp.local",
904           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
905               MDnsTransaction::SINGLE_RESULT,
906           base::BindRepeating(&MDnsTest::MockableRecordCallback,
907                               base::Unretained(this)));
908 
909   ASSERT_TRUE(transaction_privet->Start());
910 
911   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS,
912                                             nullptr))
913       .Times(Exactly(1))
914       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
915 
916   RunFor(base::Seconds(4));
917 }
918 
TEST_F(MDnsTest,TransactionMultipleRecords)919 TEST_F(MDnsTest, TransactionMultipleRecords) {
920   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
921 
922   std::unique_ptr<MDnsTransaction> transaction_privet =
923       test_client_->CreateTransaction(
924           dns_protocol::kTypePTR, "_privet._tcp.local",
925           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE,
926           base::BindRepeating(&MDnsTest::MockableRecordCallback,
927                               base::Unretained(this)));
928 
929   ASSERT_TRUE(transaction_privet->Start());
930 
931   PtrRecordCopyContainer record_privet;
932   PtrRecordCopyContainer record_privet2;
933 
934   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
935       .Times(Exactly(2))
936       .WillOnce(Invoke(&record_privet,
937                        &PtrRecordCopyContainer::SaveWithDummyArg))
938       .WillOnce(Invoke(&record_privet2,
939                        &PtrRecordCopyContainer::SaveWithDummyArg));
940 
941   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
942   SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
943 
944   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
945                                          "hello._privet._tcp.local"));
946 
947   EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
948                                           "zzzzz._privet._tcp.local"));
949 
950   EXPECT_CALL(*this,
951               MockableRecordCallback(MDnsTransaction::RESULT_DONE, nullptr))
952       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
953 
954   RunFor(base::Seconds(4));
955 }
956 
TEST_F(MDnsTest,TransactionReentrantDelete)957 TEST_F(MDnsTest, TransactionReentrantDelete) {
958   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
959 
960   transaction_ = test_client_->CreateTransaction(
961       dns_protocol::kTypePTR, "_privet._tcp.local",
962       MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
963           MDnsTransaction::SINGLE_RESULT,
964       base::BindRepeating(&MDnsTest::MockableRecordCallback,
965                           base::Unretained(this)));
966 
967   ASSERT_TRUE(transaction_->Start());
968 
969   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS,
970                                             nullptr))
971       .Times(Exactly(1))
972       .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction),
973                       InvokeWithoutArgs(this, &MDnsTest::Stop)));
974 
975   RunFor(base::Seconds(4));
976 
977   EXPECT_EQ(nullptr, transaction_.get());
978 }
979 
TEST_F(MDnsTest,TransactionReentrantDeleteFromCache)980 TEST_F(MDnsTest, TransactionReentrantDeleteFromCache) {
981   StrictMock<MockListenerDelegate> delegate_irrelevant;
982   std::unique_ptr<MDnsListener> listener_irrelevant =
983       test_client_->CreateListener(dns_protocol::kTypeA,
984                                    "codereview.chromium.local",
985                                    &delegate_irrelevant);
986   ASSERT_TRUE(listener_irrelevant->Start());
987 
988   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
989 
990   transaction_ = test_client_->CreateTransaction(
991       dns_protocol::kTypePTR, "_privet._tcp.local",
992       MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE,
993       base::BindRepeating(&MDnsTest::MockableRecordCallback,
994                           base::Unretained(this)));
995 
996   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
997       .Times(Exactly(1))
998       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction));
999 
1000   ASSERT_TRUE(transaction_->Start());
1001 
1002   EXPECT_EQ(nullptr, transaction_.get());
1003 }
1004 
TEST_F(MDnsTest,TransactionReentrantCacheLookupStart)1005 TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) {
1006   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
1007 
1008   std::unique_ptr<MDnsTransaction> transaction1 =
1009       test_client_->CreateTransaction(
1010           dns_protocol::kTypePTR, "_privet._tcp.local",
1011           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1012               MDnsTransaction::SINGLE_RESULT,
1013           base::BindRepeating(&MDnsTest::MockableRecordCallback,
1014                               base::Unretained(this)));
1015 
1016   std::unique_ptr<MDnsTransaction> transaction2 =
1017       test_client_->CreateTransaction(
1018           dns_protocol::kTypePTR, "_printer._tcp.local",
1019           MDnsTransaction::QUERY_CACHE | MDnsTransaction::SINGLE_RESULT,
1020           base::BindRepeating(&MDnsTest::MockableRecordCallback2,
1021                               base::Unretained(this)));
1022 
1023   EXPECT_CALL(*this, MockableRecordCallback2(MDnsTransaction::RESULT_RECORD,
1024                                              _))
1025       .Times(Exactly(1));
1026 
1027   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD,
1028                                             _))
1029       .Times(Exactly(1))
1030       .WillOnce(IgnoreResult(InvokeWithoutArgs(transaction2.get(),
1031                                                &MDnsTransaction::Start)));
1032 
1033   ASSERT_TRUE(transaction1->Start());
1034 
1035   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
1036 }
1037 
TEST_F(MDnsTest,GoodbyePacketNotification)1038 TEST_F(MDnsTest, GoodbyePacketNotification) {
1039   StrictMock<MockListenerDelegate> delegate_privet;
1040 
1041   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1042       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1043   ASSERT_TRUE(listener_privet->Start());
1044 
1045   SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
1046 
1047   RunFor(base::Seconds(2));
1048 }
1049 
TEST_F(MDnsTest,GoodbyePacketRemoval)1050 TEST_F(MDnsTest, GoodbyePacketRemoval) {
1051   StrictMock<MockListenerDelegate> delegate_privet;
1052 
1053   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1054       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1055   ASSERT_TRUE(listener_privet->Start());
1056 
1057   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1058       .Times(Exactly(1));
1059 
1060   SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
1061 
1062   SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
1063 
1064   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
1065       .Times(Exactly(1));
1066 
1067   RunFor(base::Seconds(2));
1068 }
1069 
1070 // In order to reliably test reentrant listener deletes, we create two listeners
1071 // and have each of them delete both, so we're guaranteed to try and deliver a
1072 // callback to at least one deleted listener.
1073 
TEST_F(MDnsTest,ListenerReentrantDelete)1074 TEST_F(MDnsTest, ListenerReentrantDelete) {
1075   StrictMock<MockListenerDelegate> delegate_privet;
1076 
1077   listener1_ = test_client_->CreateListener(
1078       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1079 
1080   listener2_ = test_client_->CreateListener(
1081       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1082 
1083   ASSERT_TRUE(listener1_->Start());
1084 
1085   ASSERT_TRUE(listener2_->Start());
1086 
1087   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1088       .Times(Exactly(1))
1089       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteBothListeners));
1090 
1091   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
1092 
1093   EXPECT_EQ(nullptr, listener1_.get());
1094   EXPECT_EQ(nullptr, listener2_.get());
1095 }
1096 
ACTION_P(SaveIPAddress,ip_container)1097 ACTION_P(SaveIPAddress, ip_container) {
1098   ::testing::StaticAssertTypeEq<const RecordParsed*, arg1_type>();
1099   ::testing::StaticAssertTypeEq<IPAddress*, ip_container_type>();
1100 
1101   *ip_container = arg1->template rdata<ARecordRdata>()->address();
1102 }
1103 
TEST_F(MDnsTest,DoubleRecordDisagreeing)1104 TEST_F(MDnsTest, DoubleRecordDisagreeing) {
1105   IPAddress address;
1106   StrictMock<MockListenerDelegate> delegate_privet;
1107 
1108   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1109       dns_protocol::kTypeA, "privet.local", &delegate_privet);
1110 
1111   ASSERT_TRUE(listener_privet->Start());
1112 
1113   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1114       .Times(Exactly(1))
1115       .WillOnce(SaveIPAddress(&address));
1116 
1117   SimulatePacketReceive(kCorruptedPacketDoubleRecord,
1118                         sizeof(kCorruptedPacketDoubleRecord));
1119 
1120   EXPECT_EQ("2.3.4.5", address.ToString());
1121 }
1122 
TEST_F(MDnsTest,NsecWithListener)1123 TEST_F(MDnsTest, NsecWithListener) {
1124   StrictMock<MockListenerDelegate> delegate_privet;
1125   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1126       dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
1127 
1128   // Test to make sure nsec callback is NOT called for PTR
1129   // (which is marked as existing).
1130   StrictMock<MockListenerDelegate> delegate_privet2;
1131   std::unique_ptr<MDnsListener> listener_privet2 = test_client_->CreateListener(
1132       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet2);
1133 
1134   ASSERT_TRUE(listener_privet->Start());
1135 
1136   EXPECT_CALL(delegate_privet,
1137               OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
1138 
1139   SimulatePacketReceive(kSamplePacketNsec,
1140                         sizeof(kSamplePacketNsec));
1141 }
1142 
TEST_F(MDnsTest,NsecWithTransactionFromNetwork)1143 TEST_F(MDnsTest, NsecWithTransactionFromNetwork) {
1144   std::unique_ptr<MDnsTransaction> transaction_privet =
1145       test_client_->CreateTransaction(
1146           dns_protocol::kTypeA, "_privet._tcp.local",
1147           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1148               MDnsTransaction::SINGLE_RESULT,
1149           base::BindRepeating(&MDnsTest::MockableRecordCallback,
1150                               base::Unretained(this)));
1151 
1152   EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
1153 
1154   ASSERT_TRUE(transaction_privet->Start());
1155 
1156   EXPECT_CALL(*this,
1157               MockableRecordCallback(MDnsTransaction::RESULT_NSEC, nullptr));
1158 
1159   SimulatePacketReceive(kSamplePacketNsec,
1160                         sizeof(kSamplePacketNsec));
1161 }
1162 
TEST_F(MDnsTest,NsecWithTransactionFromCache)1163 TEST_F(MDnsTest, NsecWithTransactionFromCache) {
1164   // Force mDNS to listen.
1165   StrictMock<MockListenerDelegate> delegate_irrelevant;
1166   std::unique_ptr<MDnsListener> listener_irrelevant =
1167       test_client_->CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
1168                                    &delegate_irrelevant);
1169   listener_irrelevant->Start();
1170 
1171   SimulatePacketReceive(kSamplePacketNsec,
1172                         sizeof(kSamplePacketNsec));
1173 
1174   EXPECT_CALL(*this,
1175               MockableRecordCallback(MDnsTransaction::RESULT_NSEC, nullptr));
1176 
1177   std::unique_ptr<MDnsTransaction> transaction_privet_a =
1178       test_client_->CreateTransaction(
1179           dns_protocol::kTypeA, "_privet._tcp.local",
1180           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1181               MDnsTransaction::SINGLE_RESULT,
1182           base::BindRepeating(&MDnsTest::MockableRecordCallback,
1183                               base::Unretained(this)));
1184 
1185   ASSERT_TRUE(transaction_privet_a->Start());
1186 
1187   // Test that a PTR transaction does NOT consider the same NSEC record to be a
1188   // valid answer to the query
1189 
1190   std::unique_ptr<MDnsTransaction> transaction_privet_ptr =
1191       test_client_->CreateTransaction(
1192           dns_protocol::kTypePTR, "_privet._tcp.local",
1193           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1194               MDnsTransaction::SINGLE_RESULT,
1195           base::BindRepeating(&MDnsTest::MockableRecordCallback,
1196                               base::Unretained(this)));
1197 
1198   EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
1199 
1200   ASSERT_TRUE(transaction_privet_ptr->Start());
1201 }
1202 
TEST_F(MDnsTest,NsecConflictRemoval)1203 TEST_F(MDnsTest, NsecConflictRemoval) {
1204   StrictMock<MockListenerDelegate> delegate_privet;
1205   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1206       dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
1207 
1208   ASSERT_TRUE(listener_privet->Start());
1209 
1210   const RecordParsed* record1;
1211   const RecordParsed* record2;
1212 
1213   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1214       .WillOnce(SaveArg<1>(&record1));
1215 
1216   SimulatePacketReceive(kSamplePacketAPrivet,
1217                         sizeof(kSamplePacketAPrivet));
1218 
1219   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
1220       .WillOnce(SaveArg<1>(&record2));
1221 
1222   EXPECT_CALL(delegate_privet,
1223               OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
1224 
1225   SimulatePacketReceive(kSamplePacketNsec,
1226                         sizeof(kSamplePacketNsec));
1227 
1228   EXPECT_EQ(record1, record2);
1229 }
1230 
1231 
TEST_F(MDnsTest,RefreshQuery)1232 TEST_F(MDnsTest, RefreshQuery) {
1233   StrictMock<MockListenerDelegate> delegate_privet;
1234   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1235       dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
1236 
1237   listener_privet->SetActiveRefresh(true);
1238   ASSERT_TRUE(listener_privet->Start());
1239 
1240   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _));
1241 
1242   SimulatePacketReceive(kSamplePacketAPrivet,
1243                         sizeof(kSamplePacketAPrivet));
1244 
1245   // Expecting 2 calls (one for ipv4 and one for ipv6) for each of the 2
1246   // scheduled refresh queries.
1247   EXPECT_CALL(socket_factory_, OnSendTo(
1248       MakeString(kQueryPacketPrivetA, sizeof(kQueryPacketPrivetA))))
1249       .Times(4);
1250 
1251   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _));
1252 
1253   RunFor(base::Seconds(6));
1254 }
1255 
1256 // MDnsSocketFactory implementation that creates a single socket that will
1257 // always fail on RecvFrom. Passing this to MdnsClient is expected to result in
1258 // the client failing to start listening.
1259 class FailingSocketFactory : public MDnsSocketFactory {
CreateSockets(std::vector<std::unique_ptr<DatagramServerSocket>> * sockets)1260   void CreateSockets(
1261       std::vector<std::unique_ptr<DatagramServerSocket>>* sockets) override {
1262     auto socket =
1263         std::make_unique<MockMDnsDatagramServerSocket>(ADDRESS_FAMILY_IPV4);
1264     EXPECT_CALL(*socket, RecvFrom(_, _, _, _))
1265         .WillRepeatedly(Return(ERR_FAILED));
1266     sockets->push_back(std::move(socket));
1267   }
1268 };
1269 
TEST_F(MDnsTest,StartListeningFailure)1270 TEST_F(MDnsTest, StartListeningFailure) {
1271   test_client_ = std::make_unique<MDnsClientImpl>();
1272   FailingSocketFactory socket_factory;
1273 
1274   EXPECT_THAT(test_client_->StartListening(&socket_factory),
1275               test::IsError(ERR_FAILED));
1276 }
1277 
1278 // Test that the cache is cleared when it gets filled to unreasonable sizes.
TEST_F(MDnsTest,ClearOverfilledCache)1279 TEST_F(MDnsTest, ClearOverfilledCache) {
1280   test_client_->core()->cache_for_testing()->set_entry_limit_for_testing(1);
1281 
1282   StrictMock<MockListenerDelegate> delegate_privet;
1283   StrictMock<MockListenerDelegate> delegate_printer;
1284 
1285   PtrRecordCopyContainer record_privet;
1286   PtrRecordCopyContainer record_printer;
1287 
1288   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1289       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1290   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
1291       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
1292 
1293   ASSERT_TRUE(listener_privet->Start());
1294   ASSERT_TRUE(listener_printer->Start());
1295 
1296   bool privet_added = false;
1297   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1298       .Times(AtMost(1))
1299       .WillOnce(Assign(&privet_added, true));
1300   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
1301       .WillRepeatedly(Assign(&privet_added, false));
1302 
1303   bool printer_added = false;
1304   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1305       .Times(AtMost(1))
1306       .WillOnce(Assign(&printer_added, true));
1307   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
1308       .WillRepeatedly(Assign(&printer_added, false));
1309 
1310   // Fill past capacity and expect everything to eventually be removed.
1311   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
1312   base::RunLoop().RunUntilIdle();
1313   EXPECT_FALSE(privet_added);
1314   EXPECT_FALSE(printer_added);
1315 }
1316 
1317 // Note: These tests assume that the ipv4 socket will always be created first.
1318 // This is a simplifying assumption based on the way the code works now.
1319 class SimpleMockSocketFactory : public MDnsSocketFactory {
1320  public:
CreateSockets(std::vector<std::unique_ptr<DatagramServerSocket>> * sockets)1321   void CreateSockets(
1322       std::vector<std::unique_ptr<DatagramServerSocket>>* sockets) override {
1323     sockets->clear();
1324     sockets->swap(sockets_);
1325   }
1326 
PushSocket(std::unique_ptr<DatagramServerSocket> socket)1327   void PushSocket(std::unique_ptr<DatagramServerSocket> socket) {
1328     sockets_.push_back(std::move(socket));
1329   }
1330 
1331  private:
1332   std::vector<std::unique_ptr<DatagramServerSocket>> sockets_;
1333 };
1334 
1335 class MockMDnsConnectionDelegate : public MDnsConnection::Delegate {
1336  public:
HandlePacket(DnsResponse * response,int size)1337   void HandlePacket(DnsResponse* response, int size) override {
1338     HandlePacketInternal(std::string(response->io_buffer()->data(), size));
1339   }
1340 
1341   MOCK_METHOD1(HandlePacketInternal, void(std::string packet));
1342 
1343   MOCK_METHOD1(OnConnectionError, void(int error));
1344 };
1345 
1346 class MDnsConnectionTest : public TestWithTaskEnvironment {
1347  public:
MDnsConnectionTest()1348   MDnsConnectionTest() : connection_(&delegate_) {
1349   }
1350 
1351  protected:
1352   // Follow successful connection initialization.
SetUp()1353   void SetUp() override {
1354     auto socket_ipv4 =
1355         std::make_unique<MockMDnsDatagramServerSocket>(ADDRESS_FAMILY_IPV4);
1356     auto socket_ipv6 =
1357         std::make_unique<MockMDnsDatagramServerSocket>(ADDRESS_FAMILY_IPV6);
1358     socket_ipv4_ptr_ = socket_ipv4.get();
1359     socket_ipv6_ptr_ = socket_ipv6.get();
1360     factory_.PushSocket(std::move(socket_ipv4));
1361     factory_.PushSocket(std::move(socket_ipv6));
1362     sample_packet_ = MakeString(kSamplePacket1, sizeof(kSamplePacket1));
1363     sample_buffer_ = base::MakeRefCounted<StringIOBuffer>(sample_packet_);
1364   }
1365 
InitConnection()1366   int InitConnection() { return connection_.Init(&factory_); }
1367 
1368   StrictMock<MockMDnsConnectionDelegate> delegate_;
1369 
1370   raw_ptr<MockMDnsDatagramServerSocket> socket_ipv4_ptr_;
1371   raw_ptr<MockMDnsDatagramServerSocket> socket_ipv6_ptr_;
1372   SimpleMockSocketFactory factory_;
1373   MDnsConnection connection_;
1374   TestCompletionCallback callback_;
1375   std::string sample_packet_;
1376   scoped_refptr<IOBuffer> sample_buffer_;
1377 };
1378 
TEST_F(MDnsConnectionTest,ReceiveSynchronous)1379 TEST_F(MDnsConnectionTest, ReceiveSynchronous) {
1380   socket_ipv6_ptr_->SetResponsePacket(sample_packet_);
1381   EXPECT_CALL(*socket_ipv4_ptr_, RecvFrom(_, _, _, _))
1382       .WillOnce(Return(ERR_IO_PENDING));
1383   EXPECT_CALL(*socket_ipv6_ptr_, RecvFrom(_, _, _, _))
1384       .WillOnce(Invoke(socket_ipv6_ptr_.get(),
1385                        &MockMDnsDatagramServerSocket::HandleRecvNow))
1386       .WillOnce(Return(ERR_IO_PENDING));
1387 
1388   EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_));
1389   EXPECT_THAT(InitConnection(), test::IsOk());
1390 }
1391 
TEST_F(MDnsConnectionTest,ReceiveAsynchronous)1392 TEST_F(MDnsConnectionTest, ReceiveAsynchronous) {
1393   socket_ipv6_ptr_->SetResponsePacket(sample_packet_);
1394 
1395   EXPECT_CALL(*socket_ipv4_ptr_, RecvFrom(_, _, _, _))
1396       .WillOnce(Return(ERR_IO_PENDING));
1397   EXPECT_CALL(*socket_ipv6_ptr_, RecvFrom(_, _, _, _))
1398       .Times(2)
1399       .WillOnce(Invoke(socket_ipv6_ptr_.get(),
1400                        &MockMDnsDatagramServerSocket::HandleRecvLater))
1401       .WillOnce(Return(ERR_IO_PENDING));
1402 
1403   ASSERT_THAT(InitConnection(), test::IsOk());
1404 
1405   EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_));
1406 
1407   base::RunLoop().RunUntilIdle();
1408 }
1409 
TEST_F(MDnsConnectionTest,Error)1410 TEST_F(MDnsConnectionTest, Error) {
1411   CompletionOnceCallback callback;
1412 
1413   EXPECT_CALL(*socket_ipv4_ptr_, RecvFrom(_, _, _, _))
1414       .WillOnce(Return(ERR_IO_PENDING));
1415   EXPECT_CALL(*socket_ipv6_ptr_, RecvFrom(_, _, _, _))
1416       .WillOnce([&](auto, auto, auto, auto cb) {
1417         callback = std::move(cb);
1418         return ERR_IO_PENDING;
1419       });
1420 
1421   ASSERT_THAT(InitConnection(), test::IsOk());
1422 
1423   EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
1424   std::move(callback).Run(ERR_SOCKET_NOT_CONNECTED);
1425   base::RunLoop().RunUntilIdle();
1426 }
1427 
1428 class MDnsConnectionSendTest : public MDnsConnectionTest {
1429  protected:
SetUp()1430   void SetUp() override {
1431     MDnsConnectionTest::SetUp();
1432     EXPECT_CALL(*socket_ipv4_ptr_, RecvFrom(_, _, _, _))
1433         .WillOnce(Return(ERR_IO_PENDING));
1434     EXPECT_CALL(*socket_ipv6_ptr_, RecvFrom(_, _, _, _))
1435         .WillOnce(Return(ERR_IO_PENDING));
1436     EXPECT_THAT(InitConnection(), test::IsOk());
1437   }
1438 };
1439 
TEST_F(MDnsConnectionSendTest,Send)1440 TEST_F(MDnsConnectionSendTest, Send) {
1441   EXPECT_CALL(*socket_ipv4_ptr_,
1442               SendToInternal(sample_packet_, "224.0.0.251:5353", _));
1443   EXPECT_CALL(*socket_ipv6_ptr_,
1444               SendToInternal(sample_packet_, "[ff02::fb]:5353", _));
1445 
1446   connection_.Send(sample_buffer_, sample_packet_.size());
1447 }
1448 
TEST_F(MDnsConnectionSendTest,SendError)1449 TEST_F(MDnsConnectionSendTest, SendError) {
1450   EXPECT_CALL(*socket_ipv4_ptr_,
1451               SendToInternal(sample_packet_, "224.0.0.251:5353", _));
1452   EXPECT_CALL(*socket_ipv6_ptr_,
1453               SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
1454       .WillOnce(Return(ERR_SOCKET_NOT_CONNECTED));
1455 
1456   connection_.Send(sample_buffer_, sample_packet_.size());
1457   EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
1458   base::RunLoop().RunUntilIdle();
1459 }
1460 
TEST_F(MDnsConnectionSendTest,SendQueued)1461 TEST_F(MDnsConnectionSendTest, SendQueued) {
1462   // Send data immediately.
1463   EXPECT_CALL(*socket_ipv4_ptr_,
1464               SendToInternal(sample_packet_, "224.0.0.251:5353", _))
1465       .Times(2)
1466       .WillRepeatedly(Return(OK));
1467 
1468   CompletionOnceCallback callback;
1469   // Delay sending data. Only the first call should be made.
1470   EXPECT_CALL(*socket_ipv6_ptr_,
1471               SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
1472       .WillOnce([&](auto, auto, auto cb) {
1473         callback = std::move(cb);
1474         return ERR_IO_PENDING;
1475       });
1476 
1477   connection_.Send(sample_buffer_, sample_packet_.size());
1478   connection_.Send(sample_buffer_, sample_packet_.size());
1479 
1480   // The second IPv6 packet is not sent yet.
1481   EXPECT_CALL(*socket_ipv4_ptr_,
1482               SendToInternal(sample_packet_, "224.0.0.251:5353", _))
1483       .Times(0);
1484   // Expect call for the second IPv6 packet.
1485   EXPECT_CALL(*socket_ipv6_ptr_,
1486               SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
1487       .WillOnce(Return(OK));
1488   std::move(callback).Run(OK);
1489 }
1490 
TEST(MDnsSocketTest,CreateSocket)1491 TEST(MDnsSocketTest, CreateSocket) {
1492   // Verifies that socket creation hasn't been broken.
1493   auto socket = CreateAndBindMDnsSocket(AddressFamily::ADDRESS_FAMILY_IPV4, 1,
1494                                         net::NetLog::Get());
1495   EXPECT_TRUE(socket);
1496   socket->Close();
1497 }
1498 
1499 }  // namespace net
1500