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

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

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

Powered by Google App Engine
This is Rietveld 408576698