Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: net/dns/mdns_listener_unittest.cc

Issue 15733008: Multicast DNS implementation (initial) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mdns_implementation2
Patch Set: Uploading to check comments against diff (next upload will have files renamed) Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 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.
4
5 #include "base/memory/ref_counted.h"
6 #include "base/message_loop.h"
7 #include "net/base/rand_callback.h"
8 #include "net/base/test_completion_callback.h"
9 #include "net/dns/mdns_listener_impl.h"
10 #include "net/dns/record_rdata.h"
11 #include "net/test/fake_time_system.h"
12 #include "net/udp/udp_client_socket.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 using ::testing::Invoke;
17 using ::testing::InvokeWithoutArgs;
18 using ::testing::StrictMock;
19 using ::testing::Exactly;
20 using ::testing::Return;
21 using ::testing::_;
22
23 namespace net {
24
25 namespace {
26
27 const char kSamplePacket1[] = {
28 // Header
29 0x00, 0x00, // ID is zeroed out
30 0x81, 0x80, // Standard query response, RA, no error
31 0x00, 0x00, // No questions (for simplicity)
32 0x00, 0x02, // 2 RRs (answers)
33 0x00, 0x00, // 0 authority RRs
34 0x00, 0x00, // 0 additional RRs
35
36 // Answer 1
37 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
38 0x04, '_', 't', 'c', 'p',
39 0x05, 'l', 'o', 'c', 'a', 'l',
40 0x00,
41 0x00, 0x0c, // TYPE is PTR.
42 0x00, 0x01, // CLASS is IN.
43 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
44 0x24, 0x74,
45 0x00, 0x08, // RDLENGTH is 8 bytes.
46 0x05, 'h', 'e', 'l', 'l', 'o',
47 0xc0, 0x0c,
48
49 // Answer 2
50 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',
51 0xc0, 0x14, // Pointer to "._tcp.local"
52 0x00, 0x0c, // TYPE is PTR.
53 0x00, 0x01, // CLASS is IN.
54 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds.
55 0x24, 0x75,
56 0x00, 0x08, // RDLENGTH is 8 bytes.
57 0x05, 'h', 'e', 'l', 'l', 'o',
58 0xc0, 0x32
59 };
60
61 const char kCorruptedPacketBadQuestion[] = {
62 // Header
63 0x00, 0x00, // ID is zeroed out
64 0x81, 0x80, // Standard query response, RA, no error
65 0x00, 0x01, // One question
66 0x00, 0x02, // 2 RRs (answers)
67 0x00, 0x00, // 0 authority RRs
68 0x00, 0x00, // 0 additional RRs
69
70 // Question is corrupted and cannot be read.
71 0x99, 'h', 'e', 'l', 'l', 'o',
72 0x00,
73 0x00, 0x00,
74 0x00, 0x00,
75
76 // Answer 1
77 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
78 0x04, '_', 't', 'c', 'p',
79 0x05, 'l', 'o', 'c', 'a', 'l',
80 0x00,
81 0x00, 0x0c, // TYPE is PTR.
82 0x00, 0x01, // CLASS is IN.
83 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
84 0x24, 0x74,
85 0x00, 0x99, // RDLENGTH is impossible
86 0x05, 'h', 'e', 'l', 'l', 'o',
87 0xc0, 0x0c,
88
89 // Answer 2
90 0x08, '_', 'p', 'r', // Useless trailing data.
91 };
92
93 const char kCorruptedPacketUnsalvagable[] = {
94 // Header
95 0x00, 0x00, // ID is zeroed out
96 0x81, 0x80, // Standard query response, RA, no error
97 0x00, 0x00, // No questions (for simplicity)
98 0x00, 0x02, // 2 RRs (answers)
99 0x00, 0x00, // 0 authority RRs
100 0x00, 0x00, // 0 additional RRs
101
102 // Answer 1
103 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
104 0x04, '_', 't', 'c', 'p',
105 0x05, 'l', 'o', 'c', 'a', 'l',
106 0x00,
107 0x00, 0x0c, // TYPE is PTR.
108 0x00, 0x01, // CLASS is IN.
109 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
110 0x24, 0x74,
111 0x00, 0x99, // RDLENGTH is impossible
112 0x05, 'h', 'e', 'l', 'l', 'o',
113 0xc0, 0x0c,
114
115 // Answer 2
116 0x08, '_', 'p', 'r', // Useless trailing data.
117 };
118
119 const char kCorruptedPacketSalvagable[] = {
120 // Header
121 0x00, 0x00, // ID is zeroed out
122 0x81, 0x80, // Standard query response, RA, no error
123 0x00, 0x00, // No questions (for simplicity)
124 0x00, 0x02, // 2 RRs (answers)
125 0x00, 0x00, // 0 authority RRs
126 0x00, 0x00, // 0 additional RRs
127
128 // Answer 1
129 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
130 0x04, '_', 't', 'c', 'p',
131 0x05, 'l', 'o', 'c', 'a', 'l',
132 0x00,
133 0x00, 0x0c, // TYPE is PTR.
134 0x00, 0x01, // CLASS is IN.
135 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
136 0x24, 0x74,
137 0x00, 0x08, // RDLENGTH is 8 bytes.
138 0x99, 'h', 'e', 'l', 'l', 'o', // Bad RDATA format.
139 0xc0, 0x0c,
140
141 // Answer 2
142 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',
143 0xc0, 0x14, // Pointer to "._tcp.local"
144 0x00, 0x0c, // TYPE is PTR.
145 0x00, 0x01, // CLASS is IN.
146 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 49 seconds.
147 0x24, 0x75,
148 0x00, 0x08, // RDLENGTH is 8 bytes.
149 0x05, 'h', 'e', 'l', 'l', 'o',
150 0xc0, 0x32
151 };
152
153 const char kSamplePacket2[] = {
154 // Header
155 0x00, 0x00, // ID is zeroed out
156 0x81, 0x80, // Standard query response, RA, no error
157 0x00, 0x00, // No questions (for simplicity)
158 0x00, 0x02, // 2 RRs (answers)
159 0x00, 0x00, // 0 authority RRs
160 0x00, 0x00, // 0 additional RRs
161
162 // Answer 1
163 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
164 0x04, '_', 't', 'c', 'p',
165 0x05, 'l', 'o', 'c', 'a', 'l',
166 0x00,
167 0x00, 0x0c, // TYPE is PTR.
168 0x00, 0x01, // CLASS is IN.
169 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
170 0x24, 0x74,
171 0x00, 0x08, // RDLENGTH is 8 bytes.
172 0x05, 'z', 'z', 'z', 'z', 'z',
173 0xc0, 0x0c,
174
175 // Answer 2
176 0x08, '_', 'p', 'r', 'i', 'n', 't', 'e', 'r',
177 0xc0, 0x14, // Pointer to "._tcp.local"
178 0x00, 0x0c, // TYPE is PTR.
179 0x00, 0x01, // CLASS is IN.
180 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
181 0x24, 0x74,
182 0x00, 0x08, // RDLENGTH is 8 bytes.
183 0x05, 'z', 'z', 'z', 'z', 'z',
184 0xc0, 0x32
185 };
186
187 const char kQueryPacketPrivet[] = {
188 // Header
189 0x00, 0x00, // ID is zeroed out
190 0x00, 0x00, // Standard query.
191 0x00, 0x01, // One question.
192 0x00, 0x00, // 0 RRs (answers)
193 0x00, 0x00, // 0 authority RRs
194 0x00, 0x00, // 0 additional RRs
195
196 // Question
197 // This part is echoed back from the respective query.
198 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
199 0x04, '_', 't', 'c', 'p',
200 0x05, 'l', 'o', 'c', 'a', 'l',
201 0x00,
202 0x00, 0x0c, // TYPE is PTR.
203 0x00, 0x01, // CLASS is IN.
204 };
205
206 const char kSamplePacketAdditionalOnly[] = {
207 // Header
208 0x00, 0x00, // ID is zeroed out
209 0x81, 0x80, // Standard query response, RA, no error
210 0x00, 0x00, // No questions (for simplicity)
211 0x00, 0x00, // 2 RRs (answers)
212 0x00, 0x00, // 0 authority RRs
213 0x00, 0x01, // 0 additional RRs
214
215 // Answer 1
216 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
217 0x04, '_', 't', 'c', 'p',
218 0x05, 'l', 'o', 'c', 'a', 'l',
219 0x00,
220 0x00, 0x0c, // TYPE is PTR.
221 0x00, 0x01, // CLASS is IN.
222 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
223 0x24, 0x74,
224 0x00, 0x08, // RDLENGTH is 8 bytes.
225 0x05, 'h', 'e', 'l', 'l', 'o',
226 0xc0, 0x0c,
227 };
228
229 class MockMDnsConnectionFactory;
230
231 class MockMDnsConnection : public MDnsConnection {
232 public:
233 MockMDnsConnection(MDnsConnection::Delegate* delegate,
234 MockMDnsConnectionFactory* factory)
235 : delegate_(delegate), factory_(factory) {
236 }
237
238 virtual ~MockMDnsConnection() {
239 }
240
241 virtual bool Init() OVERRIDE {
242 return true;
243 }
244
245 virtual bool Send(IOBuffer* buffer, unsigned size) OVERRIDE;
246
247 void SimulateRecieve(const char* packet, int size);
248
249 private:
250 DnsResponse response;
251 MDnsConnection::Delegate* delegate_;
252 MockMDnsConnectionFactory* factory_;
253 };
254
255 class MockMDnsConnectionFactory : public MDnsConnectionFactory {
256 public:
257 MockMDnsConnectionFactory() {}
258 virtual ~MockMDnsConnectionFactory() {}
259 virtual scoped_ptr<MDnsConnection> CreateConnection(
260 MDnsConnection::Delegate* delegate,
261 base::TaskRunner* task_runner) OVERRIDE;
262
263 MOCK_METHOD1(OnSend, void(std::string));
264
265 MockMDnsConnection* latest_connection() { return latest_connection_; }
266
267 private:
268 MockMDnsConnection* latest_connection_;
269 };
270
271 class MockMDnsConnectionDelegate : public MDnsConnection::Delegate {
272 public:
273 virtual void HandlePacket(DnsResponse* response, int size) {
274 OnHandlePacket(std::string(response->io_buffer()->data(), size));
275 }
276
277 MOCK_METHOD1(OnHandlePacket, void(std::string));
278 };
279
280 bool MockMDnsConnection::Send(IOBuffer* buffer, unsigned size) {
281 factory_->OnSend(std::string(buffer->data(), size));
282 return true;
283 }
284
285 void MockMDnsConnection::SimulateRecieve(const char* packet, int size) {
286 memcpy(response.io_buffer()->data(), packet, size);
287 delegate_->HandlePacket(&response, size);
288 }
289
290 scoped_ptr<MDnsConnection> MockMDnsConnectionFactory::CreateConnection(
291 MDnsConnection::Delegate* delegate,
292 base::TaskRunner* task_runner) {
293 latest_connection_ = new MockMDnsConnection(delegate, this);
294
295 return scoped_ptr<MDnsConnection>(latest_connection_);
296 }
297
298 class RecordParsedCopyContainer {
299 public:
300 RecordParsedCopyContainer() {}
301 ~RecordParsedCopyContainer() {}
302
303 bool is_set() const { return value_.get() != NULL; }
304
305 void SaveWithDummyArg(int unused, const RecordParsed* value) {
306 Save(value);
307 }
308
309 void Save(const RecordParsed* value) {
310 value_ = value->Clone();
311 }
312
313 const RecordParsed* operator->() const {
314 return value_.get();
315 }
316
317 private:
318 scoped_ptr<const RecordParsed> value_;
319 };
320
321 class MDnsTest : public ::testing::Test {
322 public:
323 MDnsTest();
324 virtual ~MDnsTest();
325 void DeleteTransaction();
326 void DeleteBothListeners();
327
328 MOCK_METHOD2(MockableRecordCallback, void(MDnsTransactionResult,
329 const RecordParsed*));
330
331 protected:
332 void ExpectPacket(const char* packet, unsigned size);
333 void SendPacket(const char* packet, unsigned size);
334 void ExpectPtrRecord(
335 const std::string& name,
336 const std::string& ptrdomain,
337 const RecordParsedCopyContainer& record);
338
339 base::MessageLoop* message_loop_;
340
341 scoped_ptr<MDnsClientImpl> test_client_;
342 IPEndPoint mdns_ipv4_endpoint_;
343 scoped_refptr<FakeTimeSystem> time_system_;
344 StrictMock<MockMDnsConnectionFactory> connection_factory_;
345
346 // Transactions and listeners that can be deleted by class methods for
347 // reentrancy tests.
348 scoped_ptr<MDnsTransaction> transaction_;
349 scoped_ptr<MDnsListener> listener1_;
350 scoped_ptr<MDnsListener> listener2_;
351 };
352
353 class MockListenerDelegate : public MDnsListener::Delegate {
354 public:
355 MOCK_METHOD2(OnRecordUpdate,
356 void(MDnsUpdateType, const RecordParsed*));
357 MOCK_METHOD2(OnNsecRecord, void(const std::string&, unsigned));
358 };
359
360 MDnsTest::MDnsTest()
361 : message_loop_(base::MessageLoop::current()) {
362 time_system_ = new FakeTimeSystem();
363 time_system_->SetNow(base::Time::FromDoubleT(1234.0));
364 test_client_.reset(new MDnsClientImpl(time_system_, time_system_,
365 &connection_factory_));
366 }
367
368 MDnsTest::~MDnsTest() {
369 }
370
371 void MDnsTest::SendPacket(const char* packet, unsigned size) {
372 connection_factory_.latest_connection()->SimulateRecieve(packet, size);
373 }
374
375 void MDnsTest::ExpectPtrRecord(
376 const std::string& name,
377 const std::string& ptrdomain,
378 const RecordParsedCopyContainer& record) {
379 EXPECT_TRUE(record.is_set());
380 EXPECT_EQ(name, record->name());
381 EXPECT_EQ(dns_protocol::kTypePTR, record->type());
382 EXPECT_EQ(dns_protocol::kClassIN, record->klass());
383 const PtrRecordRdata* rdata = record->rdata<PtrRecordRdata>();
384 EXPECT_TRUE(rdata != NULL);
385 EXPECT_EQ(ptrdomain, rdata->ptrdomain());
386 }
387
388 void MDnsTest::ExpectPacket(
389 const char* packet,
390 unsigned size) {
391 EXPECT_CALL(connection_factory_, OnSend(std::string(packet, size)));
392 }
393
394 void MDnsTest::DeleteTransaction() {
395 transaction_.reset();
396 }
397
398 void MDnsTest::DeleteBothListeners() {
399 listener1_.reset();
400 listener2_.reset();
401 }
402
403 TEST_F(MDnsTest, PassiveListeners) {
404 StrictMock<MockListenerDelegate> delegate_privet;
405 StrictMock<MockListenerDelegate> delegate_printer;
406 StrictMock<MockListenerDelegate> delegate_ptr;
407
408 RecordParsedCopyContainer record_privet;
409 RecordParsedCopyContainer record_printer;
410
411 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
412 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
413 &delegate_privet);
414 scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
415 dns_protocol::kTypePTR, "_printer._tcp.local", false, false,
416 &delegate_printer);
417 scoped_ptr<MDnsListener> listener_ptr = test_client_->CreateListener(
418 dns_protocol::kTypePTR, "", false, false, &delegate_ptr);
419
420 ASSERT_TRUE(test_client_->IsListeningForTests());
421
422 // Send the same packet twice to ensure no records are double-counted.
423
424 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
425 .Times(Exactly(1))
426 .WillOnce(Invoke(
427 &record_privet,
428 &RecordParsedCopyContainer::SaveWithDummyArg));
429
430 EXPECT_CALL(delegate_printer, OnRecordUpdate(kMDnsRecordAdded, _))
431 .Times(Exactly(1))
432 .WillOnce(Invoke(
433 &record_printer,
434 &RecordParsedCopyContainer::SaveWithDummyArg));
435
436 EXPECT_CALL(delegate_ptr, OnRecordUpdate(kMDnsRecordAdded, _))
437 .Times(Exactly(2));
438
439 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
440 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
441
442 time_system_->RunPendingTasks();
443
444 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
445 record_privet);
446
447 ExpectPtrRecord("_printer._tcp.local", "hello._printer._tcp.local",
448 record_printer);
449
450 listener_privet.reset();
451 listener_printer.reset();
452
453 ASSERT_TRUE(test_client_->IsListeningForTests());
454
455 EXPECT_CALL(delegate_ptr, OnRecordUpdate(kMDnsRecordAdded, _))
456 .Times(Exactly(2));
457
458 SendPacket(kSamplePacket2, sizeof(kSamplePacket2));
459
460 time_system_->RunPendingTasks();
461
462 // Test to make sure mdns listener is not active with no listeners present.
463 listener_ptr.reset();
464
465 time_system_->RunPendingTasks();
466
467 ASSERT_FALSE(test_client_->IsListeningForTests());
468 }
469
470 TEST_F(MDnsTest, PassiveListenersCleanup) {
471 StrictMock<MockListenerDelegate> delegate_privet;
472
473 RecordParsedCopyContainer record_privet;
474 RecordParsedCopyContainer record_privet2;
475
476 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
477 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
478 &delegate_privet);
479
480 ASSERT_TRUE(test_client_->IsListeningForTests());
481
482 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
483 .Times(Exactly(1))
484 .WillOnce(Invoke(
485 &record_privet,
486 &RecordParsedCopyContainer::SaveWithDummyArg));
487
488 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
489
490 time_system_->RunPendingTasks();
491
492 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
493 record_privet);
494
495 base::Time expiration = time_system_->Now() + base::TimeDelta::FromSeconds(
496 record_privet->ttl());
497
498 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordRemoved, _))
499 .Times(Exactly(1))
500 .WillOnce(Invoke(
501 &record_privet2,
502 &RecordParsedCopyContainer::SaveWithDummyArg));
503
504 time_system_->SetNow(expiration);
505 time_system_->RunPendingTasks();
506
507 time_system_->RunPendingTasks();
508
509 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
510 record_privet2);
511 }
512
513 TEST_F(MDnsTest, PassiveListenersNotifyExisting) {
514 StrictMock<MockListenerDelegate> delegate_privet;
515 StrictMock<MockListenerDelegate> delegate_privet2;
516
517 RecordParsedCopyContainer record_privet;
518 RecordParsedCopyContainer record_privet2;
519
520 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
521 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
522 &delegate_privet);
523
524 ASSERT_TRUE(test_client_->IsListeningForTests());
525
526 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
527 .Times(Exactly(1))
528 .WillOnce(Invoke(
529 &record_privet,
530 &RecordParsedCopyContainer::SaveWithDummyArg));
531
532 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
533
534 time_system_->RunPendingTasks();
535
536 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
537 record_privet);
538
539 EXPECT_CALL(delegate_privet2, OnRecordUpdate(kMDnsRecordAdded, _))
540 .Times(Exactly(1))
541 .WillOnce(Invoke(
542 &record_privet2,
543 &RecordParsedCopyContainer::SaveWithDummyArg));
544
545 scoped_ptr<MDnsListener> listener_privet2 = test_client_->CreateListener(
546 dns_protocol::kTypePTR, "_privet._tcp.local", false, true,
547 &delegate_privet2);
548
549 time_system_->RunPendingTasks();
550
551 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
552 record_privet2);
553 }
554
555 TEST_F(MDnsTest, MalformedPacket) {
556 StrictMock<MockListenerDelegate> delegate_printer;
557
558 RecordParsedCopyContainer record_printer;
559
560 scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
561 dns_protocol::kTypePTR, "_printer._tcp.local", false, false,
562 &delegate_printer);
563
564 ASSERT_TRUE(test_client_->IsListeningForTests());
565
566 EXPECT_CALL(delegate_printer, OnRecordUpdate(kMDnsRecordAdded, _))
567 .Times(Exactly(1))
568 .WillOnce(Invoke(
569 &record_printer,
570 &RecordParsedCopyContainer::SaveWithDummyArg));
571
572 // First, send unsalvagable packet to ensure we can deal with it.
573 SendPacket(kCorruptedPacketUnsalvagable,
574 sizeof(kCorruptedPacketUnsalvagable));
575
576 // Regression test: send a packet where the question cannot be read.
577 SendPacket(kCorruptedPacketBadQuestion,
578 sizeof(kCorruptedPacketBadQuestion));
579
580 // Then send salvagable packet to ensure we can extract useful records.
581 SendPacket(kCorruptedPacketSalvagable,
582 sizeof(kCorruptedPacketSalvagable));
583
584 time_system_->RunPendingTasks();
585
586 ExpectPtrRecord("_printer._tcp.local", "hello._printer._tcp.local",
587 record_printer);
588 }
589
590 TEST_F(MDnsTest, QueryCache) {
591 StrictMock<MockListenerDelegate> delegate_privet;
592
593 RecordParsedCopyContainer record_privet;
594 std::vector<const RecordParsed*> records_from_cache;
595
596 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
597 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
598 &delegate_privet);
599
600 ASSERT_TRUE(test_client_->IsListeningForTests());
601
602 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
603 .Times(Exactly(1))
604 .WillOnce(Invoke(
605 &record_privet,
606 &RecordParsedCopyContainer::SaveWithDummyArg));
607
608 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
609
610 time_system_->RunPendingTasks();
611
612 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
613 record_privet);
614
615 listener_privet->QueryCache(&records_from_cache);
616
617 EXPECT_EQ(1u, records_from_cache.size());
618 EXPECT_EQ("_privet._tcp.local", records_from_cache.front()->name());
619 EXPECT_EQ(dns_protocol::kTypePTR, records_from_cache.front()->type());
620 EXPECT_EQ(dns_protocol::kClassIN, records_from_cache.front()->klass());
621
622 const PtrRecordRdata* ptr_rdata =
623 records_from_cache.front()->rdata<PtrRecordRdata>();
624
625 EXPECT_TRUE(ptr_rdata != NULL);
626
627 EXPECT_EQ("hello._privet._tcp.local",
628 ptr_rdata->ptrdomain());
629 }
630
631 TEST_F(MDnsTest, Query) {
632 StrictMock<MockListenerDelegate> delegate_privet;
633 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
634
635 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
636 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
637 &delegate_privet);
638
639 ASSERT_TRUE(listener_privet->SendQuery(false));
640
641 // Active listeners should send queries when created.
642 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
643
644 scoped_ptr<MDnsListener> listener_privet2 = test_client_->CreateListener(
645 dns_protocol::kTypePTR, "_privet._tcp.local", true /*active*/,
646 false /*existing*/, &delegate_privet);
647 }
648
649 TEST_F(MDnsTest, TransactionNoCache) {
650 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
651
652 scoped_ptr<MDnsTransaction> transaction_privet =
653 test_client_->CreateTransaction(
654 dns_protocol::kTypePTR, "_privet._tcp.local",
655 base::Bind(&MDnsTest::MockableRecordCallback,
656 base::Unretained(this)));
657
658 EXPECT_TRUE(test_client_->IsListeningForTests());
659
660 RecordParsedCopyContainer record_privet;
661
662 EXPECT_CALL(*this, MockableRecordCallback(kMDnsTransactionSuccess, _))
663 .Times(Exactly(1))
664 .WillOnce(Invoke(&record_privet,
665 &RecordParsedCopyContainer::SaveWithDummyArg));
666
667 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
668
669 time_system_->RunPendingTasks();
670
671 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
672 record_privet);
673
674 EXPECT_FALSE(test_client_->IsListeningForTests());
675 }
676
677 TEST_F(MDnsTest, TransactionWithCache) {
678 // Listener to force the client to listen
679 StrictMock<MockListenerDelegate> delegate_irrelevant;
680 scoped_ptr<MDnsListener> listener_irrelevant = test_client_->CreateListener(
681 dns_protocol::kTypeA, "codereview.chromium.local", false, false,
682 &delegate_irrelevant);
683
684 EXPECT_TRUE(test_client_->IsListeningForTests());
685
686 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
687
688 time_system_->RunPendingTasks();
689
690 RecordParsedCopyContainer record_privet;
691
692 EXPECT_CALL(*this, MockableRecordCallback(kMDnsTransactionSuccess, _))
693 .WillOnce(Invoke(&record_privet,
694 &RecordParsedCopyContainer::SaveWithDummyArg));
695
696 scoped_ptr<MDnsTransaction> transaction_privet =
697 test_client_->CreateTransaction(
698 dns_protocol::kTypePTR, "_privet._tcp.local",
699 base::Bind(&MDnsTest::MockableRecordCallback,
700 base::Unretained(this)));
701
702 // "Expect no packet"?
703
704 time_system_->RunPendingTasks();
705
706 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
707 record_privet);
708 }
709
710 TEST_F(MDnsTest, AdditionalRecords) {
711 StrictMock<MockListenerDelegate> delegate_privet;
712
713 RecordParsedCopyContainer record_privet;
714
715 scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
716 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
717 &delegate_privet);
718
719 ASSERT_TRUE(test_client_->IsListeningForTests());
720
721 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
722 .Times(Exactly(1))
723 .WillOnce(Invoke(
724 &record_privet,
725 &RecordParsedCopyContainer::SaveWithDummyArg));
726
727 SendPacket(kSamplePacketAdditionalOnly, sizeof(kSamplePacket1));
728
729 time_system_->RunPendingTasks();
730
731 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
732 record_privet);
733 }
734
735 TEST_F(MDnsTest, TransactionTimeout) {
736 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
737
738 scoped_ptr<MDnsTransaction> transaction_privet =
739 test_client_->CreateTransaction(
740 dns_protocol::kTypePTR, "_privet._tcp.local",
741 base::Bind(&MDnsTest::MockableRecordCallback,
742 base::Unretained(this)));
743
744 EXPECT_TRUE(test_client_->IsListeningForTests());
745
746 EXPECT_CALL(*this, MockableRecordCallback(kMDnsTransactionTimeout, NULL))
747 .Times(Exactly(1));
748
749 time_system_->SetNow(time_system_->Now() + base::TimeDelta::FromMinutes(5));
750
751 time_system_->RunPendingTasks();
752
753 EXPECT_FALSE(test_client_->IsListeningForTests());
754 }
755
756 TEST_F(MDnsTest, TransactionReentrantDelete) {
757 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
758
759 transaction_ = test_client_->CreateTransaction(
760 dns_protocol::kTypePTR, "_privet._tcp.local",
761 base::Bind(&MDnsTest::MockableRecordCallback,
762 base::Unretained(this)));
763
764 EXPECT_TRUE(test_client_->IsListeningForTests());
765
766 EXPECT_CALL(*this, MockableRecordCallback(kMDnsTransactionTimeout, NULL))
767 .Times(Exactly(1))
768 .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction));
769
770 time_system_->SetNow(time_system_->Now() + base::TimeDelta::FromMinutes(5));
771
772 time_system_->RunPendingTasks();
773
774 EXPECT_EQ(NULL, transaction_.get());
775
776 EXPECT_FALSE(test_client_->IsListeningForTests());
777 }
778
779 // In order to reliably test reentrant listener deletes, we create two listeners
780 // and have each of them delete both, so we're guaranteed to try and deliver a
781 // callback to at least one deleted listener.
782
783 TEST_F(MDnsTest, ListenerReentrantDelete) {
784 StrictMock<MockListenerDelegate> delegate_privet;
785
786 listener1_ = test_client_->CreateListener(
787 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
788 &delegate_privet);
789
790 listener2_ = test_client_->CreateListener(
791 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
792 &delegate_privet);
793
794 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
795 .Times(Exactly(1))
796 .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteBothListeners));
797
798 EXPECT_TRUE(test_client_->IsListeningForTests());
799
800 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
801
802 time_system_->RunPendingTasks();
803
804 EXPECT_EQ(NULL, listener1_.get());
805 EXPECT_EQ(NULL, listener2_.get());
806
807 EXPECT_FALSE(test_client_->IsListeningForTests());
808 }
809
810 // Connection tests. These tests are disabled because, due to their dependence
811 // on multicast networking, they are falky.
812
813 class MDnsConnectionTest : public ::testing::Test {
814 public:
815 MDnsConnectionTest() : fake_time_system_(new FakeTimeSystem),
816 connection_(&delegate_, fake_time_system_) {
817 EXPECT_TRUE(ParseIPLiteralToNumber("224.0.0.251", &multicast_address4_));
818 // TODO(noamsml): Figure out why client socket fails to connect to ipv6
819 // multicast address.
820 EXPECT_TRUE(ParseIPLiteralToNumber("::1", &multicast_address6_));
821 connection_.Init();
822 }
823 protected:
824 IPAddressNumber multicast_address4_;
825 IPAddressNumber multicast_address6_;
826 StrictMock<MockMDnsConnectionDelegate> delegate_;
827 scoped_refptr<FakeTimeSystem> fake_time_system_;
828 MDnsConnectionImpl connection_;
829 TestCompletionCallback callback_;
830 };
831
832 TEST_F(MDnsConnectionTest, DISABLED_Recieve4) {
833 scoped_refptr<IOBuffer> buf(new IOBuffer(sizeof(kSamplePacket1)));
834 memcpy(buf->data(), kSamplePacket1, sizeof(kSamplePacket1));
835 UDPSocket socket(DatagramSocket::DEFAULT_BIND,
836 RandIntCallback(),
837 NULL, NetLog::Source());
838 EXPECT_CALL(delegate_, OnHandlePacket(std::string(kSamplePacket1,
839 sizeof(kSamplePacket1))));
840
841 EXPECT_EQ(OK, socket.Connect(IPEndPoint(multicast_address4_, 5353)));
842 int rv = socket.Write(buf, sizeof(kSamplePacket1), callback_.callback());
843 if (rv == ERR_IO_PENDING) {
844 rv = callback_.GetResult(rv);
845 }
846 EXPECT_GT(rv, OK);
847 base::MessageLoop::current()->RunUntilIdle(); // Socket uses message loop.
848 fake_time_system_->RunPendingTasks();
849 }
850
851 TEST_F(MDnsConnectionTest, DISABLED_Recieve6) {
852 scoped_refptr<IOBuffer> buf(new IOBuffer(sizeof(kSamplePacket2)));
853 memcpy(buf->data(), kSamplePacket2, sizeof(kSamplePacket2));
854 UDPSocket socket(DatagramSocket::DEFAULT_BIND,
855 RandIntCallback(),
856 NULL, NetLog::Source());
857 EXPECT_CALL(delegate_, OnHandlePacket(std::string(kSamplePacket2,
858 sizeof(kSamplePacket2))));
859
860 EXPECT_EQ(OK, socket.Connect(IPEndPoint(multicast_address6_, 5353)));
861 int rv = socket.Write(buf, sizeof(kSamplePacket2), callback_.callback());
862 if (rv == ERR_IO_PENDING) {
863 rv = callback_.GetResult(rv);
864 }
865 EXPECT_GT(rv, OK);
866 base::MessageLoop::current()->RunUntilIdle(); // Socket uses message loop.
867 fake_time_system_->RunPendingTasks();
868 }
869
870 } // namespace
871
872 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698