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