xref: /aosp_15_r20/external/cronet/net/dns/mdns_client_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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   base::RunLoop loop_;
484 };
485 
486 class MockListenerDelegate : public MDnsListener::Delegate {
487  public:
488   MOCK_METHOD2(OnRecordUpdate,
489                void(MDnsListener::UpdateType update,
490                     const RecordParsed* records));
491   MOCK_METHOD2(OnNsecRecord, void(const std::string&, unsigned));
492   MOCK_METHOD0(OnCachePurged, void());
493 };
494 
SetUp()495 void MDnsTest::SetUp() {
496   test_client_ = std::make_unique<MDnsClientImpl>();
497   ASSERT_THAT(test_client_->StartListening(&socket_factory_), test::IsOk());
498 }
499 
SimulatePacketReceive(const uint8_t * packet,unsigned size)500 void MDnsTest::SimulatePacketReceive(const uint8_t* packet, unsigned size) {
501   socket_factory_.SimulateReceive(packet, size);
502 }
503 
ExpectPacket(const uint8_t * packet,unsigned size)504 void MDnsTest::ExpectPacket(const uint8_t* packet, unsigned size) {
505   EXPECT_CALL(socket_factory_, OnSendTo(MakeString(packet, size)))
506       .Times(2);
507 }
508 
DeleteTransaction()509 void MDnsTest::DeleteTransaction() {
510   transaction_.reset();
511 }
512 
DeleteBothListeners()513 void MDnsTest::DeleteBothListeners() {
514   listener1_.reset();
515   listener2_.reset();
516 }
517 
RunFor(base::TimeDelta time_period)518 void MDnsTest::RunFor(base::TimeDelta time_period) {
519   base::CancelableOnceCallback<void()> callback(
520       base::BindOnce(&MDnsTest::Stop, base::Unretained(this)));
521   base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
522       FROM_HERE, callback.callback(), time_period);
523 
524   loop_.Run();
525   callback.Cancel();
526 }
527 
Stop()528 void MDnsTest::Stop() {
529   loop_.QuitWhenIdle();
530 }
531 
TEST_F(MDnsTest,PassiveListeners)532 TEST_F(MDnsTest, PassiveListeners) {
533   StrictMock<MockListenerDelegate> delegate_privet;
534   StrictMock<MockListenerDelegate> delegate_printer;
535 
536   PtrRecordCopyContainer record_privet;
537   PtrRecordCopyContainer record_printer;
538 
539   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
540       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
541   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
542       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
543 
544   ASSERT_TRUE(listener_privet->Start());
545   ASSERT_TRUE(listener_printer->Start());
546 
547   // Send the same packet twice to ensure no records are double-counted.
548 
549   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
550       .Times(Exactly(1))
551       .WillOnce(Invoke(
552           &record_privet,
553           &PtrRecordCopyContainer::SaveWithDummyArg));
554 
555   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
556       .Times(Exactly(1))
557       .WillOnce(Invoke(
558           &record_printer,
559           &PtrRecordCopyContainer::SaveWithDummyArg));
560 
561 
562   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
563   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
564 
565   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
566                                          "hello._privet._tcp.local"));
567 
568   EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
569                                           "hello._printer._tcp.local"));
570 
571   listener_privet.reset();
572   listener_printer.reset();
573 }
574 
TEST_F(MDnsTest,PassiveListenersWithCapitalization)575 TEST_F(MDnsTest, PassiveListenersWithCapitalization) {
576   StrictMock<MockListenerDelegate> delegate_privet;
577   StrictMock<MockListenerDelegate> delegate_printer;
578 
579   PtrRecordCopyContainer record_privet;
580   PtrRecordCopyContainer record_printer;
581 
582   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
583       dns_protocol::kTypePTR, "_privet._tcp.LOCAL", &delegate_privet);
584   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
585       dns_protocol::kTypePTR, "_prinTER._Tcp.Local", &delegate_printer);
586 
587   ASSERT_TRUE(listener_privet->Start());
588   ASSERT_TRUE(listener_printer->Start());
589 
590   // Send the same packet twice to ensure no records are double-counted.
591 
592   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
593       .Times(Exactly(1))
594       .WillOnce(
595           Invoke(&record_privet, &PtrRecordCopyContainer::SaveWithDummyArg));
596 
597   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
598       .Times(Exactly(1))
599       .WillOnce(
600           Invoke(&record_printer, &PtrRecordCopyContainer::SaveWithDummyArg));
601 
602   SimulatePacketReceive(kSamplePacket1WithCapitalization,
603                         sizeof(kSamplePacket1WithCapitalization));
604   SimulatePacketReceive(kSamplePacket1WithCapitalization,
605                         sizeof(kSamplePacket1WithCapitalization));
606 
607   EXPECT_TRUE(record_privet.IsRecordWith("_privet._TCP.local",
608                                          "hello._privet._TCP.local"));
609 
610   EXPECT_TRUE(record_printer.IsRecordWith("_PrinteR._TCP.local",
611                                           "hello._PrinteR._TCP.local"));
612 
613   listener_privet.reset();
614   listener_printer.reset();
615 }
616 
TEST_F(MDnsTest,PassiveListenersCacheCleanup)617 TEST_F(MDnsTest, PassiveListenersCacheCleanup) {
618   StrictMock<MockListenerDelegate> delegate_privet;
619 
620   PtrRecordCopyContainer record_privet;
621   PtrRecordCopyContainer record_privet2;
622 
623   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
624       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
625 
626   ASSERT_TRUE(listener_privet->Start());
627 
628   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
629       .Times(Exactly(1))
630       .WillOnce(Invoke(
631           &record_privet,
632           &PtrRecordCopyContainer::SaveWithDummyArg));
633 
634   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
635 
636   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
637                                          "hello._privet._tcp.local"));
638 
639   // Expect record is removed when its TTL expires.
640   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
641       .Times(Exactly(1))
642       .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::Stop),
643                       Invoke(&record_privet2,
644                              &PtrRecordCopyContainer::SaveWithDummyArg)));
645 
646   RunFor(base::Seconds(record_privet.ttl() + 1));
647 
648   EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
649                                           "hello._privet._tcp.local"));
650 }
651 
652 // Ensure that the cleanup task scheduler won't schedule cleanup tasks in the
653 // past if the system clock creeps past the expiration time while in the
654 // cleanup dispatcher.
TEST_F(MDnsTest,CacheCleanupWithShortTTL)655 TEST_F(MDnsTest, CacheCleanupWithShortTTL) {
656   // Use a nonzero starting time as a base.
657   base::Time start_time = base::Time() + base::Seconds(1);
658 
659   auto timer = std::make_unique<MockTimer>();
660   MockTimer* timer_ptr = timer.get();
661 
662   auto owned_clock = std::make_unique<MockClock>();
663   MockClock* clock = owned_clock.get();
664   test_clock_ = std::move(owned_clock);
665   test_client_ = std::make_unique<MDnsClientImpl>(clock, std::move(timer));
666   ASSERT_THAT(test_client_->StartListening(&socket_factory_), test::IsOk());
667 
668   EXPECT_CALL(*timer_ptr, StartObserver(_, _)).Times(1);
669   EXPECT_CALL(*clock, Now())
670       .Times(3)
671       .WillRepeatedly(Return(start_time))
672       .RetiresOnSaturation();
673 
674   // Receive two records with different TTL values.
675   // TTL(privet)=1.0s
676   // TTL(printer)=3.0s
677   StrictMock<MockListenerDelegate> delegate_privet;
678   StrictMock<MockListenerDelegate> delegate_printer;
679 
680   PtrRecordCopyContainer record_privet;
681   PtrRecordCopyContainer record_printer;
682 
683   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
684       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
685   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
686       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
687 
688   ASSERT_TRUE(listener_privet->Start());
689   ASSERT_TRUE(listener_printer->Start());
690 
691   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
692       .Times(Exactly(1));
693   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
694       .Times(Exactly(1));
695 
696   SimulatePacketReceive(kSamplePacket3, sizeof(kSamplePacket3));
697 
698   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
699       .Times(Exactly(1));
700 
701   // Set the clock to 2.0s, which should clean up the 'privet' record, but not
702   // the printer. The mock clock will change Now() mid-execution from 2s to 4s.
703   // Note: expectations are FILO-ordered -- t+2 seconds is returned, then t+4.
704   EXPECT_CALL(*clock, Now())
705       .WillOnce(Return(start_time + base::Seconds(4)))
706       .RetiresOnSaturation();
707   EXPECT_CALL(*clock, Now())
708       .WillOnce(Return(start_time + base::Seconds(2)))
709       .RetiresOnSaturation();
710 
711   EXPECT_CALL(*timer_ptr, StartObserver(_, base::TimeDelta()));
712 
713   timer_ptr->Fire();
714 }
715 
TEST_F(MDnsTest,StopListening)716 TEST_F(MDnsTest, StopListening) {
717   ASSERT_TRUE(test_client_->IsListening());
718 
719   test_client_->StopListening();
720   EXPECT_FALSE(test_client_->IsListening());
721 }
722 
TEST_F(MDnsTest,StopListening_CacheCleanupScheduled)723 TEST_F(MDnsTest, StopListening_CacheCleanupScheduled) {
724   auto owned_clock = std::make_unique<base::SimpleTestClock>();
725   base::SimpleTestClock* clock = owned_clock.get();
726   test_clock_ = std::move(owned_clock);
727 
728   // Use a nonzero starting time as a base.
729   clock->SetNow(base::Time() + base::Seconds(1));
730   auto cleanup_timer = std::make_unique<base::MockOneShotTimer>();
731   base::OneShotTimer* cleanup_timer_ptr = cleanup_timer.get();
732 
733   test_client_ =
734       std::make_unique<MDnsClientImpl>(clock, std::move(cleanup_timer));
735   ASSERT_THAT(test_client_->StartListening(&socket_factory_), test::IsOk());
736   ASSERT_TRUE(test_client_->IsListening());
737 
738   // Receive one record (privet) with TTL=1s to schedule cleanup.
739   SimulatePacketReceive(kSamplePacket3, sizeof(kSamplePacket3));
740   ASSERT_TRUE(cleanup_timer_ptr->IsRunning());
741 
742   test_client_->StopListening();
743   EXPECT_FALSE(test_client_->IsListening());
744 
745   // Expect cleanup unscheduled.
746   EXPECT_FALSE(cleanup_timer_ptr->IsRunning());
747 }
748 
TEST_F(MDnsTest,MalformedPacket)749 TEST_F(MDnsTest, MalformedPacket) {
750   StrictMock<MockListenerDelegate> delegate_printer;
751 
752   PtrRecordCopyContainer record_printer;
753 
754   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
755       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
756 
757   ASSERT_TRUE(listener_printer->Start());
758 
759   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
760       .Times(Exactly(1))
761       .WillOnce(Invoke(
762           &record_printer,
763           &PtrRecordCopyContainer::SaveWithDummyArg));
764 
765   // First, send unsalvagable packet to ensure we can deal with it.
766   SimulatePacketReceive(kCorruptedPacketUnsalvagable,
767                         sizeof(kCorruptedPacketUnsalvagable));
768 
769   // Regression test: send a packet where the question cannot be read.
770   SimulatePacketReceive(kCorruptedPacketBadQuestion,
771                         sizeof(kCorruptedPacketBadQuestion));
772 
773   // Then send salvagable packet to ensure we can extract useful records.
774   SimulatePacketReceive(kCorruptedPacketSalvagable,
775                         sizeof(kCorruptedPacketSalvagable));
776 
777   EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
778                                           "hello._printer._tcp.local"));
779 }
780 
TEST_F(MDnsTest,TransactionWithEmptyCache)781 TEST_F(MDnsTest, TransactionWithEmptyCache) {
782   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
783 
784   std::unique_ptr<MDnsTransaction> transaction_privet =
785       test_client_->CreateTransaction(
786           dns_protocol::kTypePTR, "_privet._tcp.local",
787           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
788               MDnsTransaction::SINGLE_RESULT,
789           base::BindRepeating(&MDnsTest::MockableRecordCallback,
790                               base::Unretained(this)));
791 
792   ASSERT_TRUE(transaction_privet->Start());
793 
794   PtrRecordCopyContainer record_privet;
795 
796   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
797       .Times(Exactly(1))
798       .WillOnce(Invoke(&record_privet,
799                        &PtrRecordCopyContainer::SaveWithDummyArg));
800 
801   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
802 
803   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
804                                          "hello._privet._tcp.local"));
805 }
806 
TEST_F(MDnsTest,TransactionWithEmptyCacheAndCapitalization)807 TEST_F(MDnsTest, TransactionWithEmptyCacheAndCapitalization) {
808   ExpectPacket(kQueryPacketPrivetWithCapitalization,
809                sizeof(kQueryPacketPrivetWithCapitalization));
810 
811   std::unique_ptr<MDnsTransaction> transaction_privet =
812       test_client_->CreateTransaction(
813           dns_protocol::kTypePTR, "_PRIVET._tcp.local",
814           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
815               MDnsTransaction::SINGLE_RESULT,
816           base::BindRepeating(&MDnsTest::MockableRecordCallback,
817                               base::Unretained(this)));
818 
819   ASSERT_TRUE(transaction_privet->Start());
820 
821   PtrRecordCopyContainer record_privet;
822 
823   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
824       .Times(Exactly(1))
825       .WillOnce(
826           Invoke(&record_privet, &PtrRecordCopyContainer::SaveWithDummyArg));
827 
828   SimulatePacketReceive(kSamplePacket1WithCapitalization,
829                         sizeof(kSamplePacket1WithCapitalization));
830 
831   EXPECT_TRUE(record_privet.IsRecordWith("_privet._TCP.local",
832                                          "hello._privet._TCP.local"));
833 }
834 
TEST_F(MDnsTest,TransactionCacheOnlyNoResult)835 TEST_F(MDnsTest, TransactionCacheOnlyNoResult) {
836   std::unique_ptr<MDnsTransaction> transaction_privet =
837       test_client_->CreateTransaction(
838           dns_protocol::kTypePTR, "_privet._tcp.local",
839           MDnsTransaction::QUERY_CACHE | MDnsTransaction::SINGLE_RESULT,
840           base::BindRepeating(&MDnsTest::MockableRecordCallback,
841                               base::Unretained(this)));
842 
843   EXPECT_CALL(*this,
844               MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, _))
845       .Times(Exactly(1));
846 
847   ASSERT_TRUE(transaction_privet->Start());
848 }
849 
TEST_F(MDnsTest,TransactionWithCache)850 TEST_F(MDnsTest, TransactionWithCache) {
851   // Listener to force the client to listen
852   StrictMock<MockListenerDelegate> delegate_irrelevant;
853   std::unique_ptr<MDnsListener> listener_irrelevant =
854       test_client_->CreateListener(dns_protocol::kTypeA,
855                                    "codereview.chromium.local",
856                                    &delegate_irrelevant);
857 
858   ASSERT_TRUE(listener_irrelevant->Start());
859 
860   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
861 
862 
863   PtrRecordCopyContainer record_privet;
864 
865   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
866       .WillOnce(Invoke(&record_privet,
867                        &PtrRecordCopyContainer::SaveWithDummyArg));
868 
869   std::unique_ptr<MDnsTransaction> transaction_privet =
870       test_client_->CreateTransaction(
871           dns_protocol::kTypePTR, "_privet._tcp.local",
872           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
873               MDnsTransaction::SINGLE_RESULT,
874           base::BindRepeating(&MDnsTest::MockableRecordCallback,
875                               base::Unretained(this)));
876 
877   ASSERT_TRUE(transaction_privet->Start());
878 
879   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
880                                          "hello._privet._tcp.local"));
881 }
882 
TEST_F(MDnsTest,AdditionalRecords)883 TEST_F(MDnsTest, AdditionalRecords) {
884   StrictMock<MockListenerDelegate> delegate_privet;
885 
886   PtrRecordCopyContainer record_privet;
887 
888   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
889       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
890 
891   ASSERT_TRUE(listener_privet->Start());
892 
893   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
894       .Times(Exactly(1))
895       .WillOnce(Invoke(
896           &record_privet,
897           &PtrRecordCopyContainer::SaveWithDummyArg));
898 
899   SimulatePacketReceive(kSamplePacketAdditionalOnly,
900                         sizeof(kSamplePacketAdditionalOnly));
901 
902   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
903                                          "hello._privet._tcp.local"));
904 }
905 
TEST_F(MDnsTest,TransactionTimeout)906 TEST_F(MDnsTest, TransactionTimeout) {
907   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
908 
909   std::unique_ptr<MDnsTransaction> transaction_privet =
910       test_client_->CreateTransaction(
911           dns_protocol::kTypePTR, "_privet._tcp.local",
912           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
913               MDnsTransaction::SINGLE_RESULT,
914           base::BindRepeating(&MDnsTest::MockableRecordCallback,
915                               base::Unretained(this)));
916 
917   ASSERT_TRUE(transaction_privet->Start());
918 
919   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS,
920                                             nullptr))
921       .Times(Exactly(1))
922       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
923 
924   RunFor(base::Seconds(4));
925 }
926 
TEST_F(MDnsTest,TransactionMultipleRecords)927 TEST_F(MDnsTest, TransactionMultipleRecords) {
928   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
929 
930   std::unique_ptr<MDnsTransaction> transaction_privet =
931       test_client_->CreateTransaction(
932           dns_protocol::kTypePTR, "_privet._tcp.local",
933           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE,
934           base::BindRepeating(&MDnsTest::MockableRecordCallback,
935                               base::Unretained(this)));
936 
937   ASSERT_TRUE(transaction_privet->Start());
938 
939   PtrRecordCopyContainer record_privet;
940   PtrRecordCopyContainer record_privet2;
941 
942   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
943       .Times(Exactly(2))
944       .WillOnce(Invoke(&record_privet,
945                        &PtrRecordCopyContainer::SaveWithDummyArg))
946       .WillOnce(Invoke(&record_privet2,
947                        &PtrRecordCopyContainer::SaveWithDummyArg));
948 
949   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
950   SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
951 
952   EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
953                                          "hello._privet._tcp.local"));
954 
955   EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
956                                           "zzzzz._privet._tcp.local"));
957 
958   EXPECT_CALL(*this,
959               MockableRecordCallback(MDnsTransaction::RESULT_DONE, nullptr))
960       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
961 
962   RunFor(base::Seconds(4));
963 }
964 
TEST_F(MDnsTest,TransactionReentrantDelete)965 TEST_F(MDnsTest, TransactionReentrantDelete) {
966   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
967 
968   transaction_ = test_client_->CreateTransaction(
969       dns_protocol::kTypePTR, "_privet._tcp.local",
970       MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
971           MDnsTransaction::SINGLE_RESULT,
972       base::BindRepeating(&MDnsTest::MockableRecordCallback,
973                           base::Unretained(this)));
974 
975   ASSERT_TRUE(transaction_->Start());
976 
977   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS,
978                                             nullptr))
979       .Times(Exactly(1))
980       .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction),
981                       InvokeWithoutArgs(this, &MDnsTest::Stop)));
982 
983   RunFor(base::Seconds(4));
984 
985   EXPECT_EQ(nullptr, transaction_.get());
986 }
987 
TEST_F(MDnsTest,TransactionReentrantDeleteFromCache)988 TEST_F(MDnsTest, TransactionReentrantDeleteFromCache) {
989   StrictMock<MockListenerDelegate> delegate_irrelevant;
990   std::unique_ptr<MDnsListener> listener_irrelevant =
991       test_client_->CreateListener(dns_protocol::kTypeA,
992                                    "codereview.chromium.local",
993                                    &delegate_irrelevant);
994   ASSERT_TRUE(listener_irrelevant->Start());
995 
996   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
997 
998   transaction_ = test_client_->CreateTransaction(
999       dns_protocol::kTypePTR, "_privet._tcp.local",
1000       MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE,
1001       base::BindRepeating(&MDnsTest::MockableRecordCallback,
1002                           base::Unretained(this)));
1003 
1004   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
1005       .Times(Exactly(1))
1006       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction));
1007 
1008   ASSERT_TRUE(transaction_->Start());
1009 
1010   EXPECT_EQ(nullptr, transaction_.get());
1011 }
1012 
TEST_F(MDnsTest,TransactionReentrantCacheLookupStart)1013 TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) {
1014   ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
1015 
1016   std::unique_ptr<MDnsTransaction> transaction1 =
1017       test_client_->CreateTransaction(
1018           dns_protocol::kTypePTR, "_privet._tcp.local",
1019           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1020               MDnsTransaction::SINGLE_RESULT,
1021           base::BindRepeating(&MDnsTest::MockableRecordCallback,
1022                               base::Unretained(this)));
1023 
1024   std::unique_ptr<MDnsTransaction> transaction2 =
1025       test_client_->CreateTransaction(
1026           dns_protocol::kTypePTR, "_printer._tcp.local",
1027           MDnsTransaction::QUERY_CACHE | MDnsTransaction::SINGLE_RESULT,
1028           base::BindRepeating(&MDnsTest::MockableRecordCallback2,
1029                               base::Unretained(this)));
1030 
1031   EXPECT_CALL(*this, MockableRecordCallback2(MDnsTransaction::RESULT_RECORD,
1032                                              _))
1033       .Times(Exactly(1));
1034 
1035   EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD,
1036                                             _))
1037       .Times(Exactly(1))
1038       .WillOnce(IgnoreResult(InvokeWithoutArgs(transaction2.get(),
1039                                                &MDnsTransaction::Start)));
1040 
1041   ASSERT_TRUE(transaction1->Start());
1042 
1043   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
1044 }
1045 
TEST_F(MDnsTest,GoodbyePacketNotification)1046 TEST_F(MDnsTest, GoodbyePacketNotification) {
1047   StrictMock<MockListenerDelegate> delegate_privet;
1048 
1049   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1050       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1051   ASSERT_TRUE(listener_privet->Start());
1052 
1053   SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
1054 
1055   RunFor(base::Seconds(2));
1056 }
1057 
TEST_F(MDnsTest,GoodbyePacketRemoval)1058 TEST_F(MDnsTest, GoodbyePacketRemoval) {
1059   StrictMock<MockListenerDelegate> delegate_privet;
1060 
1061   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1062       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1063   ASSERT_TRUE(listener_privet->Start());
1064 
1065   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1066       .Times(Exactly(1));
1067 
1068   SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
1069 
1070   SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
1071 
1072   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
1073       .Times(Exactly(1));
1074 
1075   RunFor(base::Seconds(2));
1076 }
1077 
1078 // In order to reliably test reentrant listener deletes, we create two listeners
1079 // and have each of them delete both, so we're guaranteed to try and deliver a
1080 // callback to at least one deleted listener.
1081 
TEST_F(MDnsTest,ListenerReentrantDelete)1082 TEST_F(MDnsTest, ListenerReentrantDelete) {
1083   StrictMock<MockListenerDelegate> delegate_privet;
1084 
1085   listener1_ = test_client_->CreateListener(
1086       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1087 
1088   listener2_ = test_client_->CreateListener(
1089       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1090 
1091   ASSERT_TRUE(listener1_->Start());
1092 
1093   ASSERT_TRUE(listener2_->Start());
1094 
1095   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1096       .Times(Exactly(1))
1097       .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteBothListeners));
1098 
1099   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
1100 
1101   EXPECT_EQ(nullptr, listener1_.get());
1102   EXPECT_EQ(nullptr, listener2_.get());
1103 }
1104 
ACTION_P(SaveIPAddress,ip_container)1105 ACTION_P(SaveIPAddress, ip_container) {
1106   ::testing::StaticAssertTypeEq<const RecordParsed*, arg1_type>();
1107   ::testing::StaticAssertTypeEq<IPAddress*, ip_container_type>();
1108 
1109   *ip_container = arg1->template rdata<ARecordRdata>()->address();
1110 }
1111 
TEST_F(MDnsTest,DoubleRecordDisagreeing)1112 TEST_F(MDnsTest, DoubleRecordDisagreeing) {
1113   IPAddress address;
1114   StrictMock<MockListenerDelegate> delegate_privet;
1115 
1116   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1117       dns_protocol::kTypeA, "privet.local", &delegate_privet);
1118 
1119   ASSERT_TRUE(listener_privet->Start());
1120 
1121   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1122       .Times(Exactly(1))
1123       .WillOnce(SaveIPAddress(&address));
1124 
1125   SimulatePacketReceive(kCorruptedPacketDoubleRecord,
1126                         sizeof(kCorruptedPacketDoubleRecord));
1127 
1128   EXPECT_EQ("2.3.4.5", address.ToString());
1129 }
1130 
TEST_F(MDnsTest,NsecWithListener)1131 TEST_F(MDnsTest, NsecWithListener) {
1132   StrictMock<MockListenerDelegate> delegate_privet;
1133   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1134       dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
1135 
1136   // Test to make sure nsec callback is NOT called for PTR
1137   // (which is marked as existing).
1138   StrictMock<MockListenerDelegate> delegate_privet2;
1139   std::unique_ptr<MDnsListener> listener_privet2 = test_client_->CreateListener(
1140       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet2);
1141 
1142   ASSERT_TRUE(listener_privet->Start());
1143 
1144   EXPECT_CALL(delegate_privet,
1145               OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
1146 
1147   SimulatePacketReceive(kSamplePacketNsec,
1148                         sizeof(kSamplePacketNsec));
1149 }
1150 
TEST_F(MDnsTest,NsecWithTransactionFromNetwork)1151 TEST_F(MDnsTest, NsecWithTransactionFromNetwork) {
1152   std::unique_ptr<MDnsTransaction> transaction_privet =
1153       test_client_->CreateTransaction(
1154           dns_protocol::kTypeA, "_privet._tcp.local",
1155           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1156               MDnsTransaction::SINGLE_RESULT,
1157           base::BindRepeating(&MDnsTest::MockableRecordCallback,
1158                               base::Unretained(this)));
1159 
1160   EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
1161 
1162   ASSERT_TRUE(transaction_privet->Start());
1163 
1164   EXPECT_CALL(*this,
1165               MockableRecordCallback(MDnsTransaction::RESULT_NSEC, nullptr));
1166 
1167   SimulatePacketReceive(kSamplePacketNsec,
1168                         sizeof(kSamplePacketNsec));
1169 }
1170 
TEST_F(MDnsTest,NsecWithTransactionFromCache)1171 TEST_F(MDnsTest, NsecWithTransactionFromCache) {
1172   // Force mDNS to listen.
1173   StrictMock<MockListenerDelegate> delegate_irrelevant;
1174   std::unique_ptr<MDnsListener> listener_irrelevant =
1175       test_client_->CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
1176                                    &delegate_irrelevant);
1177   listener_irrelevant->Start();
1178 
1179   SimulatePacketReceive(kSamplePacketNsec,
1180                         sizeof(kSamplePacketNsec));
1181 
1182   EXPECT_CALL(*this,
1183               MockableRecordCallback(MDnsTransaction::RESULT_NSEC, nullptr));
1184 
1185   std::unique_ptr<MDnsTransaction> transaction_privet_a =
1186       test_client_->CreateTransaction(
1187           dns_protocol::kTypeA, "_privet._tcp.local",
1188           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1189               MDnsTransaction::SINGLE_RESULT,
1190           base::BindRepeating(&MDnsTest::MockableRecordCallback,
1191                               base::Unretained(this)));
1192 
1193   ASSERT_TRUE(transaction_privet_a->Start());
1194 
1195   // Test that a PTR transaction does NOT consider the same NSEC record to be a
1196   // valid answer to the query
1197 
1198   std::unique_ptr<MDnsTransaction> transaction_privet_ptr =
1199       test_client_->CreateTransaction(
1200           dns_protocol::kTypePTR, "_privet._tcp.local",
1201           MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1202               MDnsTransaction::SINGLE_RESULT,
1203           base::BindRepeating(&MDnsTest::MockableRecordCallback,
1204                               base::Unretained(this)));
1205 
1206   EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
1207 
1208   ASSERT_TRUE(transaction_privet_ptr->Start());
1209 }
1210 
TEST_F(MDnsTest,NsecConflictRemoval)1211 TEST_F(MDnsTest, NsecConflictRemoval) {
1212   StrictMock<MockListenerDelegate> delegate_privet;
1213   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1214       dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
1215 
1216   ASSERT_TRUE(listener_privet->Start());
1217 
1218   const RecordParsed* record1;
1219   const RecordParsed* record2;
1220 
1221   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1222       .WillOnce(SaveArg<1>(&record1));
1223 
1224   SimulatePacketReceive(kSamplePacketAPrivet,
1225                         sizeof(kSamplePacketAPrivet));
1226 
1227   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
1228       .WillOnce(SaveArg<1>(&record2));
1229 
1230   EXPECT_CALL(delegate_privet,
1231               OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
1232 
1233   SimulatePacketReceive(kSamplePacketNsec,
1234                         sizeof(kSamplePacketNsec));
1235 
1236   EXPECT_EQ(record1, record2);
1237 }
1238 
1239 // TODO(https://crbug.com/1274091): Flaky on fuchsia.
1240 #if BUILDFLAG(IS_FUCHSIA)
1241 #define MAYBE_RefreshQuery DISABLED_RefreshQuery
1242 #else
1243 #define MAYBE_RefreshQuery RefreshQuery
1244 #endif
TEST_F(MDnsTest,MAYBE_RefreshQuery)1245 TEST_F(MDnsTest, MAYBE_RefreshQuery) {
1246   StrictMock<MockListenerDelegate> delegate_privet;
1247   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1248       dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
1249 
1250   listener_privet->SetActiveRefresh(true);
1251   ASSERT_TRUE(listener_privet->Start());
1252 
1253   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _));
1254 
1255   SimulatePacketReceive(kSamplePacketAPrivet,
1256                         sizeof(kSamplePacketAPrivet));
1257 
1258   // Expecting 2 calls (one for ipv4 and one for ipv6) for each of the 2
1259   // scheduled refresh queries.
1260   EXPECT_CALL(socket_factory_, OnSendTo(
1261       MakeString(kQueryPacketPrivetA, sizeof(kQueryPacketPrivetA))))
1262       .Times(4);
1263 
1264   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _));
1265 
1266   RunFor(base::Seconds(6));
1267 }
1268 
1269 // MDnsSocketFactory implementation that creates a single socket that will
1270 // always fail on RecvFrom. Passing this to MdnsClient is expected to result in
1271 // the client failing to start listening.
1272 class FailingSocketFactory : public MDnsSocketFactory {
CreateSockets(std::vector<std::unique_ptr<DatagramServerSocket>> * sockets)1273   void CreateSockets(
1274       std::vector<std::unique_ptr<DatagramServerSocket>>* sockets) override {
1275     auto socket =
1276         std::make_unique<MockMDnsDatagramServerSocket>(ADDRESS_FAMILY_IPV4);
1277     EXPECT_CALL(*socket, RecvFrom(_, _, _, _))
1278         .WillRepeatedly(Return(ERR_FAILED));
1279     sockets->push_back(std::move(socket));
1280   }
1281 };
1282 
TEST_F(MDnsTest,StartListeningFailure)1283 TEST_F(MDnsTest, StartListeningFailure) {
1284   test_client_ = std::make_unique<MDnsClientImpl>();
1285   FailingSocketFactory socket_factory;
1286 
1287   EXPECT_THAT(test_client_->StartListening(&socket_factory),
1288               test::IsError(ERR_FAILED));
1289 }
1290 
1291 // Test that the cache is cleared when it gets filled to unreasonable sizes.
TEST_F(MDnsTest,ClearOverfilledCache)1292 TEST_F(MDnsTest, ClearOverfilledCache) {
1293   test_client_->core()->cache_for_testing()->set_entry_limit_for_testing(1);
1294 
1295   StrictMock<MockListenerDelegate> delegate_privet;
1296   StrictMock<MockListenerDelegate> delegate_printer;
1297 
1298   PtrRecordCopyContainer record_privet;
1299   PtrRecordCopyContainer record_printer;
1300 
1301   std::unique_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1302       dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
1303   std::unique_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
1304       dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
1305 
1306   ASSERT_TRUE(listener_privet->Start());
1307   ASSERT_TRUE(listener_printer->Start());
1308 
1309   bool privet_added = false;
1310   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1311       .Times(AtMost(1))
1312       .WillOnce(Assign(&privet_added, true));
1313   EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
1314       .WillRepeatedly(Assign(&privet_added, false));
1315 
1316   bool printer_added = false;
1317   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1318       .Times(AtMost(1))
1319       .WillOnce(Assign(&printer_added, true));
1320   EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
1321       .WillRepeatedly(Assign(&printer_added, false));
1322 
1323   // Fill past capacity and expect everything to eventually be removed.
1324   SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
1325   base::RunLoop().RunUntilIdle();
1326   EXPECT_FALSE(privet_added);
1327   EXPECT_FALSE(printer_added);
1328 }
1329 
1330 // Note: These tests assume that the ipv4 socket will always be created first.
1331 // This is a simplifying assumption based on the way the code works now.
1332 class SimpleMockSocketFactory : public MDnsSocketFactory {
1333  public:
CreateSockets(std::vector<std::unique_ptr<DatagramServerSocket>> * sockets)1334   void CreateSockets(
1335       std::vector<std::unique_ptr<DatagramServerSocket>>* sockets) override {
1336     sockets->clear();
1337     sockets->swap(sockets_);
1338   }
1339 
PushSocket(std::unique_ptr<DatagramServerSocket> socket)1340   void PushSocket(std::unique_ptr<DatagramServerSocket> socket) {
1341     sockets_.push_back(std::move(socket));
1342   }
1343 
1344  private:
1345   std::vector<std::unique_ptr<DatagramServerSocket>> sockets_;
1346 };
1347 
1348 class MockMDnsConnectionDelegate : public MDnsConnection::Delegate {
1349  public:
HandlePacket(DnsResponse * response,int size)1350   void HandlePacket(DnsResponse* response, int size) override {
1351     HandlePacketInternal(std::string(response->io_buffer()->data(), size));
1352   }
1353 
1354   MOCK_METHOD1(HandlePacketInternal, void(std::string packet));
1355 
1356   MOCK_METHOD1(OnConnectionError, void(int error));
1357 };
1358 
1359 class MDnsConnectionTest : public TestWithTaskEnvironment {
1360  public:
MDnsConnectionTest()1361   MDnsConnectionTest() : connection_(&delegate_) {
1362   }
1363 
1364  protected:
1365   // Follow successful connection initialization.
SetUp()1366   void SetUp() override {
1367     auto socket_ipv4 =
1368         std::make_unique<MockMDnsDatagramServerSocket>(ADDRESS_FAMILY_IPV4);
1369     auto socket_ipv6 =
1370         std::make_unique<MockMDnsDatagramServerSocket>(ADDRESS_FAMILY_IPV6);
1371     socket_ipv4_ptr_ = socket_ipv4.get();
1372     socket_ipv6_ptr_ = socket_ipv6.get();
1373     factory_.PushSocket(std::move(socket_ipv4));
1374     factory_.PushSocket(std::move(socket_ipv6));
1375     sample_packet_ = MakeString(kSamplePacket1, sizeof(kSamplePacket1));
1376     sample_buffer_ = base::MakeRefCounted<StringIOBuffer>(sample_packet_);
1377   }
1378 
InitConnection()1379   int InitConnection() { return connection_.Init(&factory_); }
1380 
1381   StrictMock<MockMDnsConnectionDelegate> delegate_;
1382 
1383   raw_ptr<MockMDnsDatagramServerSocket, DanglingUntriaged> socket_ipv4_ptr_;
1384   raw_ptr<MockMDnsDatagramServerSocket, DanglingUntriaged> socket_ipv6_ptr_;
1385   SimpleMockSocketFactory factory_;
1386   MDnsConnection connection_;
1387   TestCompletionCallback callback_;
1388   std::string sample_packet_;
1389   scoped_refptr<IOBuffer> sample_buffer_;
1390 };
1391 
TEST_F(MDnsConnectionTest,ReceiveSynchronous)1392 TEST_F(MDnsConnectionTest, ReceiveSynchronous) {
1393   socket_ipv6_ptr_->SetResponsePacket(sample_packet_);
1394   EXPECT_CALL(*socket_ipv4_ptr_, RecvFrom(_, _, _, _))
1395       .WillOnce(Return(ERR_IO_PENDING));
1396   EXPECT_CALL(*socket_ipv6_ptr_, RecvFrom(_, _, _, _))
1397       .WillOnce(Invoke(socket_ipv6_ptr_.get(),
1398                        &MockMDnsDatagramServerSocket::HandleRecvNow))
1399       .WillOnce(Return(ERR_IO_PENDING));
1400 
1401   EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_));
1402   EXPECT_THAT(InitConnection(), test::IsOk());
1403 }
1404 
TEST_F(MDnsConnectionTest,ReceiveAsynchronous)1405 TEST_F(MDnsConnectionTest, ReceiveAsynchronous) {
1406   socket_ipv6_ptr_->SetResponsePacket(sample_packet_);
1407 
1408   EXPECT_CALL(*socket_ipv4_ptr_, RecvFrom(_, _, _, _))
1409       .WillOnce(Return(ERR_IO_PENDING));
1410   EXPECT_CALL(*socket_ipv6_ptr_, RecvFrom(_, _, _, _))
1411       .Times(2)
1412       .WillOnce(Invoke(socket_ipv6_ptr_.get(),
1413                        &MockMDnsDatagramServerSocket::HandleRecvLater))
1414       .WillOnce(Return(ERR_IO_PENDING));
1415 
1416   ASSERT_THAT(InitConnection(), test::IsOk());
1417 
1418   EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_));
1419 
1420   base::RunLoop().RunUntilIdle();
1421 }
1422 
TEST_F(MDnsConnectionTest,Error)1423 TEST_F(MDnsConnectionTest, Error) {
1424   CompletionOnceCallback callback;
1425 
1426   EXPECT_CALL(*socket_ipv4_ptr_, RecvFrom(_, _, _, _))
1427       .WillOnce(Return(ERR_IO_PENDING));
1428   EXPECT_CALL(*socket_ipv6_ptr_, RecvFrom(_, _, _, _))
1429       .WillOnce([&](auto, auto, auto, auto cb) {
1430         callback = std::move(cb);
1431         return ERR_IO_PENDING;
1432       });
1433 
1434   ASSERT_THAT(InitConnection(), test::IsOk());
1435 
1436   EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
1437   std::move(callback).Run(ERR_SOCKET_NOT_CONNECTED);
1438   base::RunLoop().RunUntilIdle();
1439 }
1440 
1441 class MDnsConnectionSendTest : public MDnsConnectionTest {
1442  protected:
SetUp()1443   void SetUp() override {
1444     MDnsConnectionTest::SetUp();
1445     EXPECT_CALL(*socket_ipv4_ptr_, RecvFrom(_, _, _, _))
1446         .WillOnce(Return(ERR_IO_PENDING));
1447     EXPECT_CALL(*socket_ipv6_ptr_, RecvFrom(_, _, _, _))
1448         .WillOnce(Return(ERR_IO_PENDING));
1449     EXPECT_THAT(InitConnection(), test::IsOk());
1450   }
1451 };
1452 
TEST_F(MDnsConnectionSendTest,Send)1453 TEST_F(MDnsConnectionSendTest, Send) {
1454   EXPECT_CALL(*socket_ipv4_ptr_,
1455               SendToInternal(sample_packet_, "224.0.0.251:5353", _));
1456   EXPECT_CALL(*socket_ipv6_ptr_,
1457               SendToInternal(sample_packet_, "[ff02::fb]:5353", _));
1458 
1459   connection_.Send(sample_buffer_, sample_packet_.size());
1460 }
1461 
TEST_F(MDnsConnectionSendTest,SendError)1462 TEST_F(MDnsConnectionSendTest, SendError) {
1463   EXPECT_CALL(*socket_ipv4_ptr_,
1464               SendToInternal(sample_packet_, "224.0.0.251:5353", _));
1465   EXPECT_CALL(*socket_ipv6_ptr_,
1466               SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
1467       .WillOnce(Return(ERR_SOCKET_NOT_CONNECTED));
1468 
1469   connection_.Send(sample_buffer_, sample_packet_.size());
1470   EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
1471   base::RunLoop().RunUntilIdle();
1472 }
1473 
TEST_F(MDnsConnectionSendTest,SendQueued)1474 TEST_F(MDnsConnectionSendTest, SendQueued) {
1475   // Send data immediately.
1476   EXPECT_CALL(*socket_ipv4_ptr_,
1477               SendToInternal(sample_packet_, "224.0.0.251:5353", _))
1478       .Times(2)
1479       .WillRepeatedly(Return(OK));
1480 
1481   CompletionOnceCallback callback;
1482   // Delay sending data. Only the first call should be made.
1483   EXPECT_CALL(*socket_ipv6_ptr_,
1484               SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
1485       .WillOnce([&](auto, auto, auto cb) {
1486         callback = std::move(cb);
1487         return ERR_IO_PENDING;
1488       });
1489 
1490   connection_.Send(sample_buffer_, sample_packet_.size());
1491   connection_.Send(sample_buffer_, sample_packet_.size());
1492 
1493   // The second IPv6 packet is not sent yet.
1494   EXPECT_CALL(*socket_ipv4_ptr_,
1495               SendToInternal(sample_packet_, "224.0.0.251:5353", _))
1496       .Times(0);
1497   // Expect call for the second IPv6 packet.
1498   EXPECT_CALL(*socket_ipv6_ptr_,
1499               SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
1500       .WillOnce(Return(OK));
1501   std::move(callback).Run(OK);
1502 }
1503 
TEST(MDnsSocketTest,CreateSocket)1504 TEST(MDnsSocketTest, CreateSocket) {
1505   // Verifies that socket creation hasn't been broken.
1506   auto socket = CreateAndBindMDnsSocket(AddressFamily::ADDRESS_FAMILY_IPV4, 1,
1507                                         net::NetLog::Get());
1508   EXPECT_TRUE(socket);
1509   socket->Close();
1510 }
1511 
1512 }  // namespace net
1513