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