ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / net / dns / mdns_client_unittest.cc
blob70514f3bcddfdff02caa0bc19514b596702f01f1
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <queue>
7 #include "base/memory/ref_counted.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/time/clock.h"
10 #include "base/time/default_clock.h"
11 #include "base/timer/mock_timer.h"
12 #include "net/base/rand_callback.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/dns/mdns_client_impl.h"
15 #include "net/dns/mock_mdns_socket_factory.h"
16 #include "net/dns/record_rdata.h"
17 #include "net/udp/udp_client_socket.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using ::testing::Invoke;
22 using ::testing::InvokeWithoutArgs;
23 using ::testing::StrictMock;
24 using ::testing::NiceMock;
25 using ::testing::Exactly;
26 using ::testing::Return;
27 using ::testing::SaveArg;
28 using ::testing::_;
30 namespace net {
32 namespace {
34 const uint8 kSamplePacket1[] = {
35 // Header
36 0x00, 0x00, // ID is zeroed out
37 0x81, 0x80, // Standard query response, RA, no error
38 0x00, 0x00, // No questions (for simplicity)
39 0x00, 0x02, // 2 RRs (answers)
40 0x00, 0x00, // 0 authority RRs
41 0x00, 0x00, // 0 additional RRs
43 // Answer 1
44 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
45 0x04, '_', 't', 'c', 'p',
46 0x05, 'l', 'o', 'c', 'a', 'l',
47 0x00,
48 0x00, 0x0c, // TYPE is PTR.
49 0x00, 0x01, // CLASS is IN.
50 0x00, 0x00, // TTL (4 bytes) is 1 second;
51 0x00, 0x01,
52 0x00, 0x08, // RDLENGTH is 8 bytes.
53 0x05, 'h', 'e', 'l', 'l', 'o',
54 0xc0, 0x0c,
56 // Answer 2
57 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',
58 0xc0, 0x14, // Pointer to "._tcp.local"
59 0x00, 0x0c, // TYPE is PTR.
60 0x00, 0x01, // CLASS is IN.
61 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds.
62 0x24, 0x75,
63 0x00, 0x08, // RDLENGTH is 8 bytes.
64 0x05, 'h', 'e', 'l', 'l', 'o',
65 0xc0, 0x32
68 const uint8 kCorruptedPacketBadQuestion[] = {
69 // Header
70 0x00, 0x00, // ID is zeroed out
71 0x81, 0x80, // Standard query response, RA, no error
72 0x00, 0x01, // One question
73 0x00, 0x02, // 2 RRs (answers)
74 0x00, 0x00, // 0 authority RRs
75 0x00, 0x00, // 0 additional RRs
77 // Question is corrupted and cannot be read.
78 0x99, 'h', 'e', 'l', 'l', 'o',
79 0x00,
80 0x00, 0x00,
81 0x00, 0x00,
83 // Answer 1
84 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
85 0x04, '_', 't', 'c', 'p',
86 0x05, 'l', 'o', 'c', 'a', 'l',
87 0x00,
88 0x00, 0x0c, // TYPE is PTR.
89 0x00, 0x01, // CLASS is IN.
90 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
91 0x24, 0x74,
92 0x00, 0x99, // RDLENGTH is impossible
93 0x05, 'h', 'e', 'l', 'l', 'o',
94 0xc0, 0x0c,
96 // Answer 2
97 0x08, '_', 'p', 'r', // Useless trailing data.
100 const uint8 kCorruptedPacketUnsalvagable[] = {
101 // Header
102 0x00, 0x00, // ID is zeroed out
103 0x81, 0x80, // Standard query response, RA, no error
104 0x00, 0x00, // No questions (for simplicity)
105 0x00, 0x02, // 2 RRs (answers)
106 0x00, 0x00, // 0 authority RRs
107 0x00, 0x00, // 0 additional RRs
109 // Answer 1
110 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
111 0x04, '_', 't', 'c', 'p',
112 0x05, 'l', 'o', 'c', 'a', 'l',
113 0x00,
114 0x00, 0x0c, // TYPE is PTR.
115 0x00, 0x01, // CLASS is IN.
116 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
117 0x24, 0x74,
118 0x00, 0x99, // RDLENGTH is impossible
119 0x05, 'h', 'e', 'l', 'l', 'o',
120 0xc0, 0x0c,
122 // Answer 2
123 0x08, '_', 'p', 'r', // Useless trailing data.
126 const uint8 kCorruptedPacketDoubleRecord[] = {
127 // Header
128 0x00, 0x00, // ID is zeroed out
129 0x81, 0x80, // Standard query response, RA, no error
130 0x00, 0x00, // No questions (for simplicity)
131 0x00, 0x02, // 2 RRs (answers)
132 0x00, 0x00, // 0 authority RRs
133 0x00, 0x00, // 0 additional RRs
135 // Answer 1
136 0x06, 'p', 'r', 'i', 'v', 'e', 't',
137 0x05, 'l', 'o', 'c', 'a', 'l',
138 0x00,
139 0x00, 0x01, // TYPE is A.
140 0x00, 0x01, // CLASS is IN.
141 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
142 0x24, 0x74,
143 0x00, 0x04, // RDLENGTH is 4
144 0x05, 0x03,
145 0xc0, 0x0c,
147 // Answer 2 -- Same key
148 0x06, 'p', 'r', 'i', 'v', 'e', 't',
149 0x05, 'l', 'o', 'c', 'a', 'l',
150 0x00,
151 0x00, 0x01, // TYPE is A.
152 0x00, 0x01, // CLASS is IN.
153 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
154 0x24, 0x74,
155 0x00, 0x04, // RDLENGTH is 4
156 0x02, 0x03,
157 0x04, 0x05,
160 const uint8 kCorruptedPacketSalvagable[] = {
161 // Header
162 0x00, 0x00, // ID is zeroed out
163 0x81, 0x80, // Standard query response, RA, no error
164 0x00, 0x00, // No questions (for simplicity)
165 0x00, 0x02, // 2 RRs (answers)
166 0x00, 0x00, // 0 authority RRs
167 0x00, 0x00, // 0 additional RRs
169 // Answer 1
170 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
171 0x04, '_', 't', 'c', 'p',
172 0x05, 'l', 'o', 'c', 'a', 'l',
173 0x00,
174 0x00, 0x0c, // TYPE is PTR.
175 0x00, 0x01, // CLASS is IN.
176 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
177 0x24, 0x74,
178 0x00, 0x08, // RDLENGTH is 8 bytes.
179 0x99, 'h', 'e', 'l', 'l', 'o', // Bad RDATA format.
180 0xc0, 0x0c,
182 // Answer 2
183 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',
184 0xc0, 0x14, // Pointer to "._tcp.local"
185 0x00, 0x0c, // TYPE is PTR.
186 0x00, 0x01, // CLASS is IN.
187 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds.
188 0x24, 0x75,
189 0x00, 0x08, // RDLENGTH is 8 bytes.
190 0x05, 'h', 'e', 'l', 'l', 'o',
191 0xc0, 0x32
194 const uint8 kSamplePacket2[] = {
195 // Header
196 0x00, 0x00, // ID is zeroed out
197 0x81, 0x80, // Standard query response, RA, no error
198 0x00, 0x00, // No questions (for simplicity)
199 0x00, 0x02, // 2 RRs (answers)
200 0x00, 0x00, // 0 authority RRs
201 0x00, 0x00, // 0 additional RRs
203 // Answer 1
204 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
205 0x04, '_', 't', 'c', 'p',
206 0x05, 'l', 'o', 'c', 'a', 'l',
207 0x00,
208 0x00, 0x0c, // TYPE is PTR.
209 0x00, 0x01, // CLASS is IN.
210 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
211 0x24, 0x74,
212 0x00, 0x08, // RDLENGTH is 8 bytes.
213 0x05, 'z', 'z', 'z', 'z', 'z',
214 0xc0, 0x0c,
216 // Answer 2
217 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',
218 0xc0, 0x14, // Pointer to "._tcp.local"
219 0x00, 0x0c, // TYPE is PTR.
220 0x00, 0x01, // CLASS is IN.
221 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
222 0x24, 0x74,
223 0x00, 0x08, // RDLENGTH is 8 bytes.
224 0x05, 'z', 'z', 'z', 'z', 'z',
225 0xc0, 0x32
228 const uint8 kSamplePacket3[] = {
229 // Header
230 0x00, 0x00, // ID is zeroed out
231 0x81, 0x80, // Standard query response, RA, no error
232 0x00, 0x00, // No questions (for simplicity)
233 0x00, 0x02, // 2 RRs (answers)
234 0x00, 0x00, // 0 authority RRs
235 0x00, 0x00, // 0 additional RRs
237 // Answer 1
238 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't', //
239 0x04, '_', 't', 'c', 'p', //
240 0x05, 'l', 'o', 'c', 'a', 'l', //
241 0x00, 0x00, 0x0c, // TYPE is PTR.
242 0x00, 0x01, // CLASS is IN.
243 0x00, 0x00, // TTL (4 bytes) is 1 second;
244 0x00, 0x01, //
245 0x00, 0x08, // RDLENGTH is 8 bytes.
246 0x05, 'h', 'e', 'l', 'l', 'o', //
247 0xc0, 0x0c, //
249 // Answer 2
250 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r', //
251 0xc0, 0x14, // Pointer to "._tcp.local"
252 0x00, 0x0c, // TYPE is PTR.
253 0x00, 0x01, // CLASS is IN.
254 0x00, 0x00, // TTL (4 bytes) is 3 seconds.
255 0x00, 0x03, //
256 0x00, 0x08, // RDLENGTH is 8 bytes.
257 0x05, 'h', 'e', 'l', 'l', 'o', //
258 0xc0, 0x32};
260 const uint8 kQueryPacketPrivet[] = {
261 // Header
262 0x00, 0x00, // ID is zeroed out
263 0x00, 0x00, // No flags.
264 0x00, 0x01, // One question.
265 0x00, 0x00, // 0 RRs (answers)
266 0x00, 0x00, // 0 authority RRs
267 0x00, 0x00, // 0 additional RRs
269 // Question
270 // This part is echoed back from the respective query.
271 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
272 0x04, '_', 't', 'c', 'p',
273 0x05, 'l', 'o', 'c', 'a', 'l',
274 0x00,
275 0x00, 0x0c, // TYPE is PTR.
276 0x00, 0x01, // CLASS is IN.
279 const uint8 kQueryPacketPrivetA[] = {
280 // Header
281 0x00, 0x00, // ID is zeroed out
282 0x00, 0x00, // No flags.
283 0x00, 0x01, // One question.
284 0x00, 0x00, // 0 RRs (answers)
285 0x00, 0x00, // 0 authority RRs
286 0x00, 0x00, // 0 additional RRs
288 // Question
289 // This part is echoed back from the respective query.
290 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
291 0x04, '_', 't', 'c', 'p',
292 0x05, 'l', 'o', 'c', 'a', 'l',
293 0x00,
294 0x00, 0x01, // TYPE is A.
295 0x00, 0x01, // CLASS is IN.
298 const uint8 kSamplePacketAdditionalOnly[] = {
299 // Header
300 0x00, 0x00, // ID is zeroed out
301 0x81, 0x80, // Standard query response, RA, no error
302 0x00, 0x00, // No questions (for simplicity)
303 0x00, 0x00, // 2 RRs (answers)
304 0x00, 0x00, // 0 authority RRs
305 0x00, 0x01, // 0 additional RRs
307 // Answer 1
308 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
309 0x04, '_', 't', 'c', 'p',
310 0x05, 'l', 'o', 'c', 'a', 'l',
311 0x00,
312 0x00, 0x0c, // TYPE is PTR.
313 0x00, 0x01, // CLASS is IN.
314 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
315 0x24, 0x74,
316 0x00, 0x08, // RDLENGTH is 8 bytes.
317 0x05, 'h', 'e', 'l', 'l', 'o',
318 0xc0, 0x0c,
321 const uint8 kSamplePacketNsec[] = {
322 // Header
323 0x00, 0x00, // ID is zeroed out
324 0x81, 0x80, // Standard query response, RA, no error
325 0x00, 0x00, // No questions (for simplicity)
326 0x00, 0x01, // 1 RR (answers)
327 0x00, 0x00, // 0 authority RRs
328 0x00, 0x00, // 0 additional RRs
330 // Answer 1
331 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
332 0x04, '_', 't', 'c', 'p',
333 0x05, 'l', 'o', 'c', 'a', 'l',
334 0x00,
335 0x00, 0x2f, // TYPE is NSEC.
336 0x00, 0x01, // CLASS is IN.
337 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
338 0x24, 0x74,
339 0x00, 0x06, // RDLENGTH is 6 bytes.
340 0xc0, 0x0c,
341 0x00, 0x02, 0x00, 0x08 // Only A record present
344 const uint8 kSamplePacketAPrivet[] = {
345 // Header
346 0x00, 0x00, // ID is zeroed out
347 0x81, 0x80, // Standard query response, RA, no error
348 0x00, 0x00, // No questions (for simplicity)
349 0x00, 0x01, // 1 RR (answers)
350 0x00, 0x00, // 0 authority RRs
351 0x00, 0x00, // 0 additional RRs
353 // Answer 1
354 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
355 0x04, '_', 't', 'c', 'p',
356 0x05, 'l', 'o', 'c', 'a', 'l',
357 0x00,
358 0x00, 0x01, // TYPE is A.
359 0x00, 0x01, // CLASS is IN.
360 0x00, 0x00, // TTL (4 bytes) is 5 seconds
361 0x00, 0x05,
362 0x00, 0x04, // RDLENGTH is 4 bytes.
363 0xc0, 0x0c,
364 0x00, 0x02,
367 const uint8 kSamplePacketGoodbye[] = {
368 // Header
369 0x00, 0x00, // ID is zeroed out
370 0x81, 0x80, // Standard query response, RA, no error
371 0x00, 0x00, // No questions (for simplicity)
372 0x00, 0x01, // 2 RRs (answers)
373 0x00, 0x00, // 0 authority RRs
374 0x00, 0x00, // 0 additional RRs
376 // Answer 1
377 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
378 0x04, '_', 't', 'c', 'p',
379 0x05, 'l', 'o', 'c', 'a', 'l',
380 0x00,
381 0x00, 0x0c, // TYPE is PTR.
382 0x00, 0x01, // CLASS is IN.
383 0x00, 0x00, // TTL (4 bytes) is zero;
384 0x00, 0x00,
385 0x00, 0x08, // RDLENGTH is 8 bytes.
386 0x05, 'z', 'z', 'z', 'z', 'z',
387 0xc0, 0x0c,
390 std::string MakeString(const uint8* data, unsigned size) {
391 return std::string(reinterpret_cast<const char*>(data), size);
394 class PtrRecordCopyContainer {
395 public:
396 PtrRecordCopyContainer() {}
397 ~PtrRecordCopyContainer() {}
399 bool is_set() const { return set_; }
401 void SaveWithDummyArg(int unused, const RecordParsed* value) {
402 Save(value);
405 void Save(const RecordParsed* value) {
406 set_ = true;
407 name_ = value->name();
408 ptrdomain_ = value->rdata<PtrRecordRdata>()->ptrdomain();
409 ttl_ = value->ttl();
412 bool IsRecordWith(std::string name, std::string ptrdomain) {
413 return set_ && name_ == name && ptrdomain_ == ptrdomain;
416 const std::string& name() { return name_; }
417 const std::string& ptrdomain() { return ptrdomain_; }
418 int ttl() { return ttl_; }
420 private:
421 bool set_;
422 std::string name_;
423 std::string ptrdomain_;
424 int ttl_;
427 class MockClock : public base::DefaultClock {
428 public:
429 MockClock() : base::DefaultClock() {}
430 virtual ~MockClock() {}
432 MOCK_METHOD0(Now, base::Time());
434 private:
435 DISALLOW_COPY_AND_ASSIGN(MockClock);
438 class MockTimer : public base::MockTimer {
439 public:
440 MockTimer() : base::MockTimer(false, false) {}
441 ~MockTimer() {}
443 void Start(const tracked_objects::Location& posted_from,
444 base::TimeDelta delay,
445 const base::Closure& user_task) {
446 StartObserver(posted_from, delay, user_task);
447 base::MockTimer::Start(posted_from, delay, user_task);
450 // StartObserver is invoked when MockTimer::Start() is called.
451 // Does not replace the behavior of MockTimer::Start().
452 MOCK_METHOD3(StartObserver,
453 void(const tracked_objects::Location& posted_from,
454 base::TimeDelta delay,
455 const base::Closure& user_task));
457 private:
458 DISALLOW_COPY_AND_ASSIGN(MockTimer);
461 } // namespace
463 class MDnsTest : public ::testing::Test {
464 public:
465 void SetUp() override;
466 void DeleteTransaction();
467 void DeleteBothListeners();
468 void RunFor(base::TimeDelta time_period);
469 void Stop();
471 MOCK_METHOD2(MockableRecordCallback, void(MDnsTransaction::Result result,
472 const RecordParsed* record));
474 MOCK_METHOD2(MockableRecordCallback2, void(MDnsTransaction::Result result,
475 const RecordParsed* record));
477 protected:
478 void ExpectPacket(const uint8* packet, unsigned size);
479 void SimulatePacketReceive(const uint8* packet, unsigned size);
481 scoped_ptr<MDnsClientImpl> test_client_;
482 IPEndPoint mdns_ipv4_endpoint_;
483 StrictMock<MockMDnsSocketFactory> socket_factory_;
485 // Transactions and listeners that can be deleted by class methods for
486 // reentrancy tests.
487 scoped_ptr<MDnsTransaction> transaction_;
488 scoped_ptr<MDnsListener> listener1_;
489 scoped_ptr<MDnsListener> listener2_;
492 class MockListenerDelegate : public MDnsListener::Delegate {
493 public:
494 MOCK_METHOD2(OnRecordUpdate,
495 void(MDnsListener::UpdateType update,
496 const RecordParsed* records));
497 MOCK_METHOD2(OnNsecRecord, void(const std::string&, unsigned));
498 MOCK_METHOD0(OnCachePurged, void());
501 void MDnsTest::SetUp() {
502 test_client_.reset(new MDnsClientImpl());
503 test_client_->StartListening(&socket_factory_);
506 void MDnsTest::SimulatePacketReceive(const uint8* packet, unsigned size) {
507 socket_factory_.SimulateReceive(packet, size);
510 void MDnsTest::ExpectPacket(const uint8* packet, unsigned size) {
511 EXPECT_CALL(socket_factory_, OnSendTo(MakeString(packet, size)))
512 .Times(2);
515 void MDnsTest::DeleteTransaction() {
516 transaction_.reset();
519 void MDnsTest::DeleteBothListeners() {
520 listener1_.reset();
521 listener2_.reset();
524 void MDnsTest::RunFor(base::TimeDelta time_period) {
525 base::CancelableCallback<void()> callback(base::Bind(&MDnsTest::Stop,
526 base::Unretained(this)));
527 base::MessageLoop::current()->PostDelayedTask(
528 FROM_HERE, callback.callback(), time_period);
530 base::MessageLoop::current()->Run();
531 callback.Cancel();
534 void MDnsTest::Stop() {
535 base::MessageLoop::current()->Quit();
538 TEST_F(MDnsTest, PassiveListeners) {
539 StrictMock<MockListenerDelegate> delegate_privet;
540 StrictMock<MockListenerDelegate> delegate_printer;
542 PtrRecordCopyContainer record_privet;
543 PtrRecordCopyContainer record_printer;
545 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
546 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
547 scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
548 dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
550 ASSERT_TRUE(listener_privet->Start());
551 ASSERT_TRUE(listener_printer->Start());
553 // Send the same packet twice to ensure no records are double-counted.
555 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
556 .Times(Exactly(1))
557 .WillOnce(Invoke(
558 &record_privet,
559 &PtrRecordCopyContainer::SaveWithDummyArg));
561 EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
562 .Times(Exactly(1))
563 .WillOnce(Invoke(
564 &record_printer,
565 &PtrRecordCopyContainer::SaveWithDummyArg));
568 SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
569 SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
571 EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
572 "hello._privet._tcp.local"));
574 EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
575 "hello._printer._tcp.local"));
577 listener_privet.reset();
578 listener_printer.reset();
581 TEST_F(MDnsTest, PassiveListenersCacheCleanup) {
582 StrictMock<MockListenerDelegate> delegate_privet;
584 PtrRecordCopyContainer record_privet;
585 PtrRecordCopyContainer record_privet2;
587 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
588 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
590 ASSERT_TRUE(listener_privet->Start());
592 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
593 .Times(Exactly(1))
594 .WillOnce(Invoke(
595 &record_privet,
596 &PtrRecordCopyContainer::SaveWithDummyArg));
598 SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
600 EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
601 "hello._privet._tcp.local"));
603 // Expect record is removed when its TTL expires.
604 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
605 .Times(Exactly(1))
606 .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::Stop),
607 Invoke(&record_privet2,
608 &PtrRecordCopyContainer::SaveWithDummyArg)));
610 RunFor(base::TimeDelta::FromSeconds(record_privet.ttl() + 1));
612 EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
613 "hello._privet._tcp.local"));
616 // Ensure that the cleanup task scheduler won't schedule cleanup tasks in the
617 // past if the system clock creeps past the expiration time while in the
618 // cleanup dispatcher.
619 TEST_F(MDnsTest, CacheCleanupWithShortTTL) {
620 // Use a nonzero starting time as a base.
621 base::Time start_time = base::Time() + base::TimeDelta::FromSeconds(1);
623 MockClock* clock = new MockClock;
624 MockTimer* timer = new MockTimer;
626 test_client_.reset(
627 new MDnsClientImpl(make_scoped_ptr(clock), make_scoped_ptr(timer)));
628 test_client_->StartListening(&socket_factory_);
630 EXPECT_CALL(*timer, StartObserver(_, _, _)).Times(1);
631 EXPECT_CALL(*clock, Now())
632 .Times(3)
633 .WillRepeatedly(Return(start_time))
634 .RetiresOnSaturation();
636 // Receive two records with different TTL values.
637 // TTL(privet)=1.0s
638 // TTL(printer)=3.0s
639 StrictMock<MockListenerDelegate> delegate_privet;
640 StrictMock<MockListenerDelegate> delegate_printer;
642 PtrRecordCopyContainer record_privet;
643 PtrRecordCopyContainer record_printer;
645 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
646 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
647 scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
648 dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
650 ASSERT_TRUE(listener_privet->Start());
651 ASSERT_TRUE(listener_printer->Start());
653 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
654 .Times(Exactly(1));
655 EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
656 .Times(Exactly(1));
658 SimulatePacketReceive(kSamplePacket3, sizeof(kSamplePacket3));
660 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
661 .Times(Exactly(1));
663 // Set the clock to 2.0s, which should clean up the 'privet' record, but not
664 // the printer. The mock clock will change Now() mid-execution from 2s to 4s.
665 // Note: expectations are FILO-ordered -- t+2 seconds is returned, then t+4.
666 EXPECT_CALL(*clock, Now())
667 .WillOnce(Return(start_time + base::TimeDelta::FromSeconds(4)))
668 .RetiresOnSaturation();
669 EXPECT_CALL(*clock, Now())
670 .WillOnce(Return(start_time + base::TimeDelta::FromSeconds(2)))
671 .RetiresOnSaturation();
673 EXPECT_CALL(*timer, StartObserver(_, base::TimeDelta(), _));
675 timer->Fire();
678 TEST_F(MDnsTest, MalformedPacket) {
679 StrictMock<MockListenerDelegate> delegate_printer;
681 PtrRecordCopyContainer record_printer;
683 scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
684 dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
686 ASSERT_TRUE(listener_printer->Start());
688 EXPECT_CALL(delegate_printer, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
689 .Times(Exactly(1))
690 .WillOnce(Invoke(
691 &record_printer,
692 &PtrRecordCopyContainer::SaveWithDummyArg));
694 // First, send unsalvagable packet to ensure we can deal with it.
695 SimulatePacketReceive(kCorruptedPacketUnsalvagable,
696 sizeof(kCorruptedPacketUnsalvagable));
698 // Regression test: send a packet where the question cannot be read.
699 SimulatePacketReceive(kCorruptedPacketBadQuestion,
700 sizeof(kCorruptedPacketBadQuestion));
702 // Then send salvagable packet to ensure we can extract useful records.
703 SimulatePacketReceive(kCorruptedPacketSalvagable,
704 sizeof(kCorruptedPacketSalvagable));
706 EXPECT_TRUE(record_printer.IsRecordWith("_printer._tcp.local",
707 "hello._printer._tcp.local"));
710 TEST_F(MDnsTest, TransactionWithEmptyCache) {
711 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
713 scoped_ptr<MDnsTransaction> transaction_privet =
714 test_client_->CreateTransaction(
715 dns_protocol::kTypePTR, "_privet._tcp.local",
716 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
717 MDnsTransaction::SINGLE_RESULT,
718 base::Bind(&MDnsTest::MockableRecordCallback,
719 base::Unretained(this)));
721 ASSERT_TRUE(transaction_privet->Start());
723 PtrRecordCopyContainer record_privet;
725 EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
726 .Times(Exactly(1))
727 .WillOnce(Invoke(&record_privet,
728 &PtrRecordCopyContainer::SaveWithDummyArg));
730 SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
732 EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
733 "hello._privet._tcp.local"));
736 TEST_F(MDnsTest, TransactionCacheOnlyNoResult) {
737 scoped_ptr<MDnsTransaction> transaction_privet =
738 test_client_->CreateTransaction(
739 dns_protocol::kTypePTR, "_privet._tcp.local",
740 MDnsTransaction::QUERY_CACHE | MDnsTransaction::SINGLE_RESULT,
741 base::Bind(&MDnsTest::MockableRecordCallback,
742 base::Unretained(this)));
744 EXPECT_CALL(*this,
745 MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, _))
746 .Times(Exactly(1));
748 ASSERT_TRUE(transaction_privet->Start());
751 TEST_F(MDnsTest, TransactionWithCache) {
752 // Listener to force the client to listen
753 StrictMock<MockListenerDelegate> delegate_irrelevant;
754 scoped_ptr<MDnsListener> listener_irrelevant = test_client_->CreateListener(
755 dns_protocol::kTypeA, "codereview.chromium.local", &delegate_irrelevant);
757 ASSERT_TRUE(listener_irrelevant->Start());
759 SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
762 PtrRecordCopyContainer record_privet;
764 EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
765 .WillOnce(Invoke(&record_privet,
766 &PtrRecordCopyContainer::SaveWithDummyArg));
768 scoped_ptr<MDnsTransaction> transaction_privet =
769 test_client_->CreateTransaction(
770 dns_protocol::kTypePTR, "_privet._tcp.local",
771 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
772 MDnsTransaction::SINGLE_RESULT,
773 base::Bind(&MDnsTest::MockableRecordCallback,
774 base::Unretained(this)));
776 ASSERT_TRUE(transaction_privet->Start());
778 EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
779 "hello._privet._tcp.local"));
782 TEST_F(MDnsTest, AdditionalRecords) {
783 StrictMock<MockListenerDelegate> delegate_privet;
785 PtrRecordCopyContainer record_privet;
787 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
788 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
790 ASSERT_TRUE(listener_privet->Start());
792 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
793 .Times(Exactly(1))
794 .WillOnce(Invoke(
795 &record_privet,
796 &PtrRecordCopyContainer::SaveWithDummyArg));
798 SimulatePacketReceive(kSamplePacketAdditionalOnly,
799 sizeof(kSamplePacketAdditionalOnly));
801 EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
802 "hello._privet._tcp.local"));
805 TEST_F(MDnsTest, TransactionTimeout) {
806 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
808 scoped_ptr<MDnsTransaction> transaction_privet =
809 test_client_->CreateTransaction(
810 dns_protocol::kTypePTR, "_privet._tcp.local",
811 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
812 MDnsTransaction::SINGLE_RESULT,
813 base::Bind(&MDnsTest::MockableRecordCallback,
814 base::Unretained(this)));
816 ASSERT_TRUE(transaction_privet->Start());
818 EXPECT_CALL(*this,
819 MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS, NULL))
820 .Times(Exactly(1))
821 .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
823 RunFor(base::TimeDelta::FromSeconds(4));
826 TEST_F(MDnsTest, TransactionMultipleRecords) {
827 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
829 scoped_ptr<MDnsTransaction> transaction_privet =
830 test_client_->CreateTransaction(
831 dns_protocol::kTypePTR, "_privet._tcp.local",
832 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE,
833 base::Bind(&MDnsTest::MockableRecordCallback,
834 base::Unretained(this)));
836 ASSERT_TRUE(transaction_privet->Start());
838 PtrRecordCopyContainer record_privet;
839 PtrRecordCopyContainer record_privet2;
841 EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
842 .Times(Exactly(2))
843 .WillOnce(Invoke(&record_privet,
844 &PtrRecordCopyContainer::SaveWithDummyArg))
845 .WillOnce(Invoke(&record_privet2,
846 &PtrRecordCopyContainer::SaveWithDummyArg));
848 SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
849 SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
851 EXPECT_TRUE(record_privet.IsRecordWith("_privet._tcp.local",
852 "hello._privet._tcp.local"));
854 EXPECT_TRUE(record_privet2.IsRecordWith("_privet._tcp.local",
855 "zzzzz._privet._tcp.local"));
857 EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_DONE, NULL))
858 .WillOnce(InvokeWithoutArgs(this, &MDnsTest::Stop));
860 RunFor(base::TimeDelta::FromSeconds(4));
863 TEST_F(MDnsTest, TransactionReentrantDelete) {
864 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
866 transaction_ = test_client_->CreateTransaction(
867 dns_protocol::kTypePTR, "_privet._tcp.local",
868 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
869 MDnsTransaction::SINGLE_RESULT,
870 base::Bind(&MDnsTest::MockableRecordCallback, base::Unretained(this)));
872 ASSERT_TRUE(transaction_->Start());
874 EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_NO_RESULTS,
875 NULL))
876 .Times(Exactly(1))
877 .WillOnce(DoAll(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction),
878 InvokeWithoutArgs(this, &MDnsTest::Stop)));
880 RunFor(base::TimeDelta::FromSeconds(4));
882 EXPECT_EQ(NULL, transaction_.get());
885 TEST_F(MDnsTest, TransactionReentrantDeleteFromCache) {
886 StrictMock<MockListenerDelegate> delegate_irrelevant;
887 scoped_ptr<MDnsListener> listener_irrelevant = test_client_->CreateListener(
888 dns_protocol::kTypeA, "codereview.chromium.local", &delegate_irrelevant);
889 ASSERT_TRUE(listener_irrelevant->Start());
891 SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
893 transaction_ = test_client_->CreateTransaction(
894 dns_protocol::kTypePTR, "_privet._tcp.local",
895 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE,
896 base::Bind(&MDnsTest::MockableRecordCallback, base::Unretained(this)));
898 EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD, _))
899 .Times(Exactly(1))
900 .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction));
902 ASSERT_TRUE(transaction_->Start());
904 EXPECT_EQ(NULL, transaction_.get());
907 TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) {
908 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
910 scoped_ptr<MDnsTransaction> transaction1 = test_client_->CreateTransaction(
911 dns_protocol::kTypePTR, "_privet._tcp.local",
912 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
913 MDnsTransaction::SINGLE_RESULT,
914 base::Bind(&MDnsTest::MockableRecordCallback, base::Unretained(this)));
916 scoped_ptr<MDnsTransaction> transaction2 = test_client_->CreateTransaction(
917 dns_protocol::kTypePTR, "_printer._tcp.local",
918 MDnsTransaction::QUERY_CACHE | MDnsTransaction::SINGLE_RESULT,
919 base::Bind(&MDnsTest::MockableRecordCallback2, base::Unretained(this)));
921 EXPECT_CALL(*this, MockableRecordCallback2(MDnsTransaction::RESULT_RECORD,
923 .Times(Exactly(1));
925 EXPECT_CALL(*this, MockableRecordCallback(MDnsTransaction::RESULT_RECORD,
927 .Times(Exactly(1))
928 .WillOnce(IgnoreResult(InvokeWithoutArgs(transaction2.get(),
929 &MDnsTransaction::Start)));
931 ASSERT_TRUE(transaction1->Start());
933 SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
936 TEST_F(MDnsTest, GoodbyePacketNotification) {
937 StrictMock<MockListenerDelegate> delegate_privet;
939 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
940 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
941 ASSERT_TRUE(listener_privet->Start());
943 SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
945 RunFor(base::TimeDelta::FromSeconds(2));
948 TEST_F(MDnsTest, GoodbyePacketRemoval) {
949 StrictMock<MockListenerDelegate> delegate_privet;
951 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
952 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
953 ASSERT_TRUE(listener_privet->Start());
955 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
956 .Times(Exactly(1));
958 SimulatePacketReceive(kSamplePacket2, sizeof(kSamplePacket2));
960 SimulatePacketReceive(kSamplePacketGoodbye, sizeof(kSamplePacketGoodbye));
962 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
963 .Times(Exactly(1));
965 RunFor(base::TimeDelta::FromSeconds(2));
968 // In order to reliably test reentrant listener deletes, we create two listeners
969 // and have each of them delete both, so we're guaranteed to try and deliver a
970 // callback to at least one deleted listener.
972 TEST_F(MDnsTest, ListenerReentrantDelete) {
973 StrictMock<MockListenerDelegate> delegate_privet;
975 listener1_ = test_client_->CreateListener(
976 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
978 listener2_ = test_client_->CreateListener(
979 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
981 ASSERT_TRUE(listener1_->Start());
983 ASSERT_TRUE(listener2_->Start());
985 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
986 .Times(Exactly(1))
987 .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteBothListeners));
989 SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
991 EXPECT_EQ(NULL, listener1_.get());
992 EXPECT_EQ(NULL, listener2_.get());
995 ACTION_P(SaveIPAddress, ip_container) {
996 ::testing::StaticAssertTypeEq<const RecordParsed*, arg1_type>();
997 ::testing::StaticAssertTypeEq<IPAddressNumber*, ip_container_type>();
999 *ip_container = arg1->template rdata<ARecordRdata>()->address();
1002 TEST_F(MDnsTest, DoubleRecordDisagreeing) {
1003 IPAddressNumber address;
1004 StrictMock<MockListenerDelegate> delegate_privet;
1006 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1007 dns_protocol::kTypeA, "privet.local", &delegate_privet);
1009 ASSERT_TRUE(listener_privet->Start());
1011 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1012 .Times(Exactly(1))
1013 .WillOnce(SaveIPAddress(&address));
1015 SimulatePacketReceive(kCorruptedPacketDoubleRecord,
1016 sizeof(kCorruptedPacketDoubleRecord));
1018 EXPECT_EQ("2.3.4.5", IPAddressToString(address));
1021 TEST_F(MDnsTest, NsecWithListener) {
1022 StrictMock<MockListenerDelegate> delegate_privet;
1023 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1024 dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
1026 // Test to make sure nsec callback is NOT called for PTR
1027 // (which is marked as existing).
1028 StrictMock<MockListenerDelegate> delegate_privet2;
1029 scoped_ptr<MDnsListener> listener_privet2 = test_client_->CreateListener(
1030 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet2);
1032 ASSERT_TRUE(listener_privet->Start());
1034 EXPECT_CALL(delegate_privet,
1035 OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
1037 SimulatePacketReceive(kSamplePacketNsec,
1038 sizeof(kSamplePacketNsec));
1041 TEST_F(MDnsTest, NsecWithTransactionFromNetwork) {
1042 scoped_ptr<MDnsTransaction> transaction_privet =
1043 test_client_->CreateTransaction(
1044 dns_protocol::kTypeA, "_privet._tcp.local",
1045 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1046 MDnsTransaction::SINGLE_RESULT,
1047 base::Bind(&MDnsTest::MockableRecordCallback,
1048 base::Unretained(this)));
1050 EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
1052 ASSERT_TRUE(transaction_privet->Start());
1054 EXPECT_CALL(*this,
1055 MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL));
1057 SimulatePacketReceive(kSamplePacketNsec,
1058 sizeof(kSamplePacketNsec));
1061 TEST_F(MDnsTest, NsecWithTransactionFromCache) {
1062 // Force mDNS to listen.
1063 StrictMock<MockListenerDelegate> delegate_irrelevant;
1064 scoped_ptr<MDnsListener> listener_irrelevant = test_client_->CreateListener(
1065 dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_irrelevant);
1066 listener_irrelevant->Start();
1068 SimulatePacketReceive(kSamplePacketNsec,
1069 sizeof(kSamplePacketNsec));
1071 EXPECT_CALL(*this,
1072 MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL));
1074 scoped_ptr<MDnsTransaction> transaction_privet_a =
1075 test_client_->CreateTransaction(
1076 dns_protocol::kTypeA, "_privet._tcp.local",
1077 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1078 MDnsTransaction::SINGLE_RESULT,
1079 base::Bind(&MDnsTest::MockableRecordCallback,
1080 base::Unretained(this)));
1082 ASSERT_TRUE(transaction_privet_a->Start());
1084 // Test that a PTR transaction does NOT consider the same NSEC record to be a
1085 // valid answer to the query
1087 scoped_ptr<MDnsTransaction> transaction_privet_ptr =
1088 test_client_->CreateTransaction(
1089 dns_protocol::kTypePTR, "_privet._tcp.local",
1090 MDnsTransaction::QUERY_NETWORK | MDnsTransaction::QUERY_CACHE |
1091 MDnsTransaction::SINGLE_RESULT,
1092 base::Bind(&MDnsTest::MockableRecordCallback,
1093 base::Unretained(this)));
1095 EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
1097 ASSERT_TRUE(transaction_privet_ptr->Start());
1100 TEST_F(MDnsTest, NsecConflictRemoval) {
1101 StrictMock<MockListenerDelegate> delegate_privet;
1102 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1103 dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
1105 ASSERT_TRUE(listener_privet->Start());
1107 const RecordParsed* record1;
1108 const RecordParsed* record2;
1110 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
1111 .WillOnce(SaveArg<1>(&record1));
1113 SimulatePacketReceive(kSamplePacketAPrivet,
1114 sizeof(kSamplePacketAPrivet));
1116 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _))
1117 .WillOnce(SaveArg<1>(&record2));
1119 EXPECT_CALL(delegate_privet,
1120 OnNsecRecord("_privet._tcp.local", dns_protocol::kTypeA));
1122 SimulatePacketReceive(kSamplePacketNsec,
1123 sizeof(kSamplePacketNsec));
1125 EXPECT_EQ(record1, record2);
1129 TEST_F(MDnsTest, RefreshQuery) {
1130 StrictMock<MockListenerDelegate> delegate_privet;
1131 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
1132 dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
1134 listener_privet->SetActiveRefresh(true);
1135 ASSERT_TRUE(listener_privet->Start());
1137 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _));
1139 SimulatePacketReceive(kSamplePacketAPrivet,
1140 sizeof(kSamplePacketAPrivet));
1142 // Expecting 2 calls (one for ipv4 and one for ipv6) for each of the 2
1143 // scheduled refresh queries.
1144 EXPECT_CALL(socket_factory_, OnSendTo(
1145 MakeString(kQueryPacketPrivetA, sizeof(kQueryPacketPrivetA))))
1146 .Times(4);
1148 EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_REMOVED, _));
1150 RunFor(base::TimeDelta::FromSeconds(6));
1153 // Note: These tests assume that the ipv4 socket will always be created first.
1154 // This is a simplifying assumption based on the way the code works now.
1155 class SimpleMockSocketFactory : public MDnsSocketFactory {
1156 public:
1157 void CreateSockets(ScopedVector<DatagramServerSocket>* sockets) override {
1158 sockets->clear();
1159 sockets->swap(sockets_);
1162 void PushSocket(DatagramServerSocket* socket) {
1163 sockets_.push_back(socket);
1166 private:
1167 ScopedVector<DatagramServerSocket> sockets_;
1170 class MockMDnsConnectionDelegate : public MDnsConnection::Delegate {
1171 public:
1172 virtual void HandlePacket(DnsResponse* response, int size) {
1173 HandlePacketInternal(std::string(response->io_buffer()->data(), size));
1176 MOCK_METHOD1(HandlePacketInternal, void(std::string packet));
1178 MOCK_METHOD1(OnConnectionError, void(int error));
1181 class MDnsConnectionTest : public ::testing::Test {
1182 public:
1183 MDnsConnectionTest() : connection_(&delegate_) {
1186 protected:
1187 // Follow successful connection initialization.
1188 void SetUp() override {
1189 socket_ipv4_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV4);
1190 socket_ipv6_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV6);
1191 factory_.PushSocket(socket_ipv6_);
1192 factory_.PushSocket(socket_ipv4_);
1193 sample_packet_ = MakeString(kSamplePacket1, sizeof(kSamplePacket1));
1194 sample_buffer_ = new StringIOBuffer(sample_packet_);
1197 bool InitConnection() {
1198 return connection_.Init(&factory_);
1201 StrictMock<MockMDnsConnectionDelegate> delegate_;
1203 MockMDnsDatagramServerSocket* socket_ipv4_;
1204 MockMDnsDatagramServerSocket* socket_ipv6_;
1205 SimpleMockSocketFactory factory_;
1206 MDnsConnection connection_;
1207 TestCompletionCallback callback_;
1208 std::string sample_packet_;
1209 scoped_refptr<IOBuffer> sample_buffer_;
1212 TEST_F(MDnsConnectionTest, ReceiveSynchronous) {
1213 socket_ipv6_->SetResponsePacket(sample_packet_);
1214 EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
1215 .WillOnce(Return(ERR_IO_PENDING));
1216 EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
1217 .WillOnce(
1218 Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvNow))
1219 .WillOnce(Return(ERR_IO_PENDING));
1221 EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_));
1222 ASSERT_TRUE(InitConnection());
1225 TEST_F(MDnsConnectionTest, ReceiveAsynchronous) {
1226 socket_ipv6_->SetResponsePacket(sample_packet_);
1228 EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
1229 .WillOnce(Return(ERR_IO_PENDING));
1230 EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
1231 .Times(2)
1232 .WillOnce(
1233 Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvLater))
1234 .WillOnce(Return(ERR_IO_PENDING));
1236 ASSERT_TRUE(InitConnection());
1238 EXPECT_CALL(delegate_, HandlePacketInternal(sample_packet_));
1240 base::MessageLoop::current()->RunUntilIdle();
1243 TEST_F(MDnsConnectionTest, Error) {
1244 CompletionCallback callback;
1246 EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
1247 .WillOnce(Return(ERR_IO_PENDING));
1248 EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
1249 .WillOnce(DoAll(SaveArg<3>(&callback), Return(ERR_IO_PENDING)));
1251 ASSERT_TRUE(InitConnection());
1253 EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
1254 callback.Run(ERR_SOCKET_NOT_CONNECTED);
1255 base::MessageLoop::current()->RunUntilIdle();
1258 class MDnsConnectionSendTest : public MDnsConnectionTest {
1259 protected:
1260 void SetUp() override {
1261 MDnsConnectionTest::SetUp();
1262 EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
1263 .WillOnce(Return(ERR_IO_PENDING));
1264 EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
1265 .WillOnce(Return(ERR_IO_PENDING));
1266 EXPECT_TRUE(InitConnection());
1270 TEST_F(MDnsConnectionSendTest, Send) {
1271 EXPECT_CALL(*socket_ipv4_,
1272 SendToInternal(sample_packet_, "224.0.0.251:5353", _));
1273 EXPECT_CALL(*socket_ipv6_,
1274 SendToInternal(sample_packet_, "[ff02::fb]:5353", _));
1276 connection_.Send(sample_buffer_, sample_packet_.size());
1279 TEST_F(MDnsConnectionSendTest, SendError) {
1280 CompletionCallback callback;
1282 EXPECT_CALL(*socket_ipv4_,
1283 SendToInternal(sample_packet_, "224.0.0.251:5353", _));
1284 EXPECT_CALL(*socket_ipv6_,
1285 SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
1286 .WillOnce(DoAll(SaveArg<2>(&callback), Return(ERR_SOCKET_NOT_CONNECTED)));
1288 connection_.Send(sample_buffer_, sample_packet_.size());
1289 EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
1290 base::MessageLoop::current()->RunUntilIdle();
1293 TEST_F(MDnsConnectionSendTest, SendQueued) {
1294 // Send data immediately.
1295 EXPECT_CALL(*socket_ipv4_,
1296 SendToInternal(sample_packet_, "224.0.0.251:5353", _))
1297 .Times(2)
1298 .WillRepeatedly(Return(OK));
1300 CompletionCallback callback;
1301 // Delay sending data. Only the first call should be made.
1302 EXPECT_CALL(*socket_ipv6_,
1303 SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
1304 .WillOnce(DoAll(SaveArg<2>(&callback), Return(ERR_IO_PENDING)));
1306 connection_.Send(sample_buffer_, sample_packet_.size());
1307 connection_.Send(sample_buffer_, sample_packet_.size());
1309 // The second IPv6 packed is not sent yet.
1310 EXPECT_CALL(*socket_ipv4_,
1311 SendToInternal(sample_packet_, "224.0.0.251:5353", _))
1312 .Times(0);
1313 // Expect call for the second IPv6 packed.
1314 EXPECT_CALL(*socket_ipv6_,
1315 SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
1316 .WillOnce(Return(OK));
1317 callback.Run(OK);
1320 } // namespace net