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

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: Created 7 years, 7 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::_;
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, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
43 0x24, 0x74,
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
229 // Connect to any port on an address. Returns the bound address.
230 IPEndPoint BindToAnyPort(UDPSocket* socket,
231 const IPAddressNumber& address) {
232 IPEndPoint endpoint(address, 0);
233 int status = socket->Bind(endpoint);
234 DCHECK(status == OK);
235 status = socket->GetLocalAddress(&endpoint);
236 DCHECK(status == OK);
237
238 return endpoint;
239 }
240
241 class TestableMDnsListenerFactoryImpl : public MDnsListenerFactoryImpl {
242 public:
243 explicit TestableMDnsListenerFactoryImpl(FakeTimeSystem* time_system)
244 : MDnsListenerFactoryImpl(time_system, time_system) {
245 }
246
247 void SetIPv4SendEndpoint(const IPEndPoint& ipv4_send_endpoint) {
248 ipv4_send_endpoint_ = ipv4_send_endpoint;
249 }
250
251 void SetIPv6SendEndpoint(const IPEndPoint& ipv6_send_endpoint) {
252 ipv6_send_endpoint_ = ipv6_send_endpoint;
253 }
254
255 IPEndPoint ipv4_bind_endpoint() { return ipv4_bind_endpoint_; }
256
257 protected:
258 virtual IPEndPoint GetIPv4SendEndpoint() OVERRIDE {
259 return ipv4_send_endpoint_;
260 }
261
262 virtual IPEndPoint GetIPv6SendEndpoint() OVERRIDE {
263 return ipv6_send_endpoint_;
264 }
265
266 virtual bool BindToAddressAndMulticastGroup(
267 UDPSocket* socket,
268 const IPEndPoint& address,
269 const IPAddressNumber& group) OVERRIDE {
270 // Bind only to local address. Use address length to determine protocol.
271 IPAddressNumber local_address;
272 if (address.address().size() == kIPv4AddressSize) {
273 bool success = ParseIPLiteralToNumber("127.0.0.1",
274 &local_address);
275 DCHECK(success);
276 } else {
277 DCHECK(address.address().size() == kIPv6AddressSize);
278 bool success = ParseIPLiteralToNumber("::1",
279 &local_address);
280 DCHECK(success);
281 }
282
283 IPEndPoint bound_endpoint = BindToAnyPort(socket, local_address);
284 if (address.address().size() == kIPv4AddressSize) {
285 ipv4_bind_endpoint_ = bound_endpoint;
286 }
287 return true;
288 }
289
290 private:
291 IPEndPoint ipv4_send_endpoint_;
292 IPEndPoint ipv6_send_endpoint_;
293 IPEndPoint ipv4_bind_endpoint_;
294 };
295
296 class RecordParsedCopyContainer {
297 public:
298 RecordParsedCopyContainer() {}
299 ~RecordParsedCopyContainer() {}
300
301 bool is_set() const { return value_.get() != NULL; }
302
303 void SaveWithDummyArg(int unused, const RecordParsed* value) {
304 Save(value);
305 }
306
307 void Save(const RecordParsed* value) {
308 value_ = value->Clone();
309 }
310
311 const RecordParsed* operator->() const {
312 return value_.get();
313 }
314
315 private:
316 scoped_ptr<const RecordParsed> value_;
317 };
318
319 class MDnsTest : public ::testing::Test {
320 public:
321 MDnsTest();
322 virtual ~MDnsTest();
323 virtual void SetUp() OVERRIDE;
324 virtual void TearDown() OVERRIDE;
325 void DeleteTransaction();
326
327 MOCK_METHOD2(MockableRecordCallback, void(MDnsTransactionResult,
328 const RecordParsed*));
329
330 protected:
331 void ExpectPacket(const char* packet, unsigned size);
332 void SendPacket(const char* packet, unsigned size);
333 void ExpectPtrRecord(
334 const std::string& name,
335 const std::string& ptrdomain,
336 const RecordParsedCopyContainer& record);
337
338 base::MessageLoop* message_loop_;
339 scoped_ptr<TestableMDnsListenerFactoryImpl> test_factory_;
340 scoped_ptr<UDPSocket> client_socket_;
341 scoped_ptr<UDPSocket> server_socket_;
342 scoped_ptr<UDPSocket> server_socket6_;
343 IPEndPoint mdns_ipv4_endpoint_;
344 scoped_refptr<FakeTimeSystem> time_system_;
345
346 scoped_ptr<MDnsTransaction> transaction_;
347 };
348
349 class MockListenerDelegate : public MDnsListenerFactory::Delegate {
350 public:
351 MOCK_METHOD2(OnRecordUpdate,
352 void(MDnsUpdateType, const RecordParsed*));
353 MOCK_METHOD2(OnNSecRecord, void(const std::string&, unsigned));
354 };
355
356 MDnsTest::MDnsTest()
357 : message_loop_(base::MessageLoop::current()),
358 client_socket_(new UDPSocket(DatagramSocket::DEFAULT_BIND,
359 net::RandIntCallback(),
360 NULL,
361 net::NetLog::Source())),
szym 2013/05/24 15:32:22 To minimize flakiness, we'd test this with MockUDP
Noam Samuel 2013/05/24 21:59:18 Hm. I tend to agree that, in retrospect, using moc
Noam Samuel 2013/05/29 21:25:16 Done.
szym 2013/06/02 19:01:23 I still see UDPSocket rather than DatagramServerSo
Noam Samuel 2013/06/03 17:57:55 DatagramServerSocket doesn't support multicasting
szym 2013/06/03 18:38:30 I think so.
Noam Samuel 2013/06/04 00:08:02 Added support in interface: https://codereview.chr
362 server_socket_(new UDPSocket(DatagramSocket::DEFAULT_BIND,
363 net::RandIntCallback(),
364 NULL,
365 net::NetLog::Source())),
366 server_socket6_(new UDPSocket(DatagramSocket::DEFAULT_BIND,
367 net::RandIntCallback(),
368 NULL,
369 net::NetLog::Source())) {
370 time_system_ = new FakeTimeSystem();
371 time_system_->SetNow(base::Time::FromDoubleT(1234.0));
372 test_factory_.reset(new TestableMDnsListenerFactoryImpl(time_system_));
373 }
374
375 MDnsTest::~MDnsTest() {
376 }
377
378 void MDnsTest::SetUp() {
379 IPAddressNumber loopback4;
380 ParseIPLiteralToNumber("127.0.0.1", &loopback4);
381
382 IPAddressNumber loopback6;
383 ParseIPLiteralToNumber("::1", &loopback6);
384
385 test_factory_->SetIPv4SendEndpoint(
386 BindToAnyPort(server_socket_.get(), loopback4));
387 test_factory_->SetIPv6SendEndpoint(
388 BindToAnyPort(server_socket6_.get(), loopback6));
389
390 client_socket_->Bind(IPEndPoint(loopback4, 0));
391 }
392
393 void MDnsTest::TearDown() {
394 client_socket_->Close();
szym 2013/05/24 15:32:22 Not necessary. ~MDnsTest (called immediately after
Noam Samuel 2013/05/29 21:25:16 Done.
395 }
396
397 void MDnsTest::SendPacket(const char* packet, unsigned size) {
398 TestCompletionCallback write_callback;
399
400 scoped_refptr<IOBufferWithSize> buffer(new IOBufferWithSize(size));
401 memcpy(buffer->data(), packet, size);
402
403 int socket_result =
404 client_socket_->SendTo(buffer,
405 size,
406 test_factory_->ipv4_bind_endpoint(),
407 write_callback.callback());
408
409 if (socket_result == ERR_IO_PENDING) {
410 socket_result = write_callback.WaitForResult();
411 }
412
413 ASSERT_EQ(size, static_cast<unsigned>(socket_result));
414
415 // Since the network layer uses MessageLoop, we RunUntilIdle here
416 // so the tests do not have to.
417 MessageLoop::current()->RunUntilIdle();
418 }
419
420 void MDnsTest::ExpectPtrRecord(
421 const std::string& name,
422 const std::string& ptrdomain,
423 const RecordParsedCopyContainer& record) {
424 EXPECT_TRUE(record.is_set());
425 EXPECT_EQ(name, record->name());
426 EXPECT_EQ(dns_protocol::kTypePTR, record->type());
427 EXPECT_EQ(dns_protocol::kClassIN, record->klass());
428 const PtrRecordRdata* rdata = record->rdata<PtrRecordRdata>();
429 EXPECT_TRUE(rdata != NULL);
430 EXPECT_EQ(ptrdomain, rdata->ptrdomain());
431 }
432
433 void MDnsTest::ExpectPacket(
434 const char* packet,
435 unsigned size) {
436 TestCompletionCallback recv_callback;
437 IPEndPoint recv_endpoint;
438 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(size);
439 int rv;
440
441 do {
442 rv = server_socket_->RecvFrom(buf.get(), buf->size(),
443 &recv_endpoint, recv_callback.callback());
444
445 if (rv == ERR_IO_PENDING) {
446 rv = recv_callback.WaitForResult();
447 }
448 DCHECK_GT(rv, 0);
449 // This is an easy way to compare to addresses for a test.
450 } while (recv_endpoint.ToString() !=
451 test_factory_->ipv4_bind_endpoint().ToString());
452
453 ASSERT_EQ(static_cast<int>(size), rv);
454 ASSERT_EQ(0, memcmp(packet, buf->data(), size));
455 }
456
457 void MDnsTest::DeleteTransaction() {
458 transaction_.reset();
459 }
460
461 TEST_F(MDnsTest, PassiveListeners) {
462 StrictMock<MockListenerDelegate> delegate_privet;
463 StrictMock<MockListenerDelegate> delegate_printer;
464 StrictMock<MockListenerDelegate> delegate_ptr;
465
466 RecordParsedCopyContainer record_privet;
467 RecordParsedCopyContainer record_printer;
468
469 scoped_ptr<MDnsListener> listener_privet = test_factory_->CreateListener(
470 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
471 &delegate_privet);
472 scoped_ptr<MDnsListener> listener_printer = test_factory_->CreateListener(
473 dns_protocol::kTypePTR, "_printer._tcp.local", false, false,
474 &delegate_printer);
475 scoped_ptr<MDnsListener> listener_ptr = test_factory_->CreateListener(
476 dns_protocol::kTypePTR, "", false, false, &delegate_ptr);
477
478 ASSERT_TRUE(test_factory_->IsListeningForTests());
479
480 // Send the same packet twice to ensure no records are double-counted.
481
482 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
483 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
484
485 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
486 .Times(Exactly(1))
487 .WillOnce(Invoke(
488 &record_privet,
489 &RecordParsedCopyContainer::SaveWithDummyArg));
490
491 EXPECT_CALL(delegate_printer, OnRecordUpdate(kMDnsRecordAdded, _))
492 .Times(Exactly(1))
493 .WillOnce(Invoke(
494 &record_printer,
495 &RecordParsedCopyContainer::SaveWithDummyArg));
496
497 EXPECT_CALL(delegate_ptr, OnRecordUpdate(kMDnsRecordAdded, _))
498 .Times(Exactly(2));
499
500 time_system_->RunPendingTasks();
501
502 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
503 record_privet);
504
505 ExpectPtrRecord("_printer._tcp.local", "hello._printer._tcp.local",
506 record_printer);
507
508 listener_privet.reset();
509 listener_printer.reset();
510
511 ASSERT_TRUE(test_factory_->IsListeningForTests());
512
513 EXPECT_CALL(delegate_ptr, OnRecordUpdate(kMDnsRecordAdded, _))
514 .Times(Exactly(2));
515
516 SendPacket(kSamplePacket2, sizeof(kSamplePacket2));
517
518 time_system_->RunPendingTasks();
519
520 // Test to make sure mdns listener is not active with no listeners present.
521 listener_ptr.reset();
522
523 ASSERT_FALSE(test_factory_->IsListeningForTests());
524 }
525
526 TEST_F(MDnsTest, PassiveListenersCleanup) {
527 StrictMock<MockListenerDelegate> delegate_privet;
528
529 RecordParsedCopyContainer record_privet;
530 RecordParsedCopyContainer record_privet2;
531
532 scoped_ptr<MDnsListener> listener_privet = test_factory_->CreateListener(
533 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
534 &delegate_privet);
535
536 ASSERT_TRUE(test_factory_->IsListeningForTests());
537
538 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
539
540 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
541 .Times(Exactly(1))
542 .WillOnce(Invoke(
543 &record_privet,
544 &RecordParsedCopyContainer::SaveWithDummyArg));
545
546 time_system_->RunPendingTasks();
547
548 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
549 record_privet);
550
551 base::Time expiration = time_system_->Now() + base::TimeDelta::FromSeconds(
552 record_privet->ttl());
553
554 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordRemoved, _))
555 .Times(Exactly(1))
556 .WillOnce(Invoke(
557 &record_privet2,
558 &RecordParsedCopyContainer::SaveWithDummyArg));
559
560 time_system_->SetNow(expiration);
561 time_system_->RunPendingTasks();
562
563 time_system_->RunPendingTasks();
564
565 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
566 record_privet2);
567 }
568
569 TEST_F(MDnsTest, PassiveListenersNotifyExisting) {
570 StrictMock<MockListenerDelegate> delegate_privet;
571 StrictMock<MockListenerDelegate> delegate_privet2;
572
573 RecordParsedCopyContainer record_privet;
574 RecordParsedCopyContainer record_privet2;
575
576 scoped_ptr<MDnsListener> listener_privet = test_factory_->CreateListener(
577 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
578 &delegate_privet);
579
580 ASSERT_TRUE(test_factory_->IsListeningForTests());
581
582 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
583
584 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
585 .Times(Exactly(1))
586 .WillOnce(Invoke(
587 &record_privet,
588 &RecordParsedCopyContainer::SaveWithDummyArg));
589
590 time_system_->RunPendingTasks();
591
592 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
593 record_privet);
594
595 scoped_ptr<MDnsListener> listener_privet2 = test_factory_->CreateListener(
596 dns_protocol::kTypePTR, "_privet._tcp.local", false, true,
597 &delegate_privet2);
598
599 EXPECT_CALL(delegate_privet2, OnRecordUpdate(kMDnsRecordAdded, _))
600 .Times(Exactly(1))
601 .WillOnce(Invoke(
602 &record_privet2,
603 &RecordParsedCopyContainer::SaveWithDummyArg));
604
605 time_system_->RunPendingTasks();
606
607 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
608 record_privet2);
609 }
610
611 TEST_F(MDnsTest, MalformedPacket) {
612 StrictMock<MockListenerDelegate> delegate_printer;
613
614 RecordParsedCopyContainer record_printer;
615
616 scoped_ptr<MDnsListener> listener_printer = test_factory_->CreateListener(
617 dns_protocol::kTypePTR, "_printer._tcp.local", false, false,
618 &delegate_printer);
619
620 ASSERT_TRUE(test_factory_->IsListeningForTests());
621
622 // First, send unsalvagable packet to ensure we can deal with it.
623 SendPacket(kCorruptedPacketUnsalvagable,
624 sizeof(kCorruptedPacketUnsalvagable));
625
626 // Regression test: send a packet where the question cannot be read.
627 SendPacket(kCorruptedPacketBadQuestion,
628 sizeof(kCorruptedPacketBadQuestion));
629
630 // Then send salvagable packet to ensure we can extract useful records.
631 SendPacket(kCorruptedPacketSalvagable,
632 sizeof(kCorruptedPacketSalvagable));
633
634 EXPECT_CALL(delegate_printer, OnRecordUpdate(kMDnsRecordAdded, _))
635 .Times(Exactly(1))
636 .WillOnce(Invoke(
637 &record_printer,
638 &RecordParsedCopyContainer::SaveWithDummyArg));
639
640 time_system_->RunPendingTasks();
641
642 ExpectPtrRecord("_printer._tcp.local", "hello._printer._tcp.local",
643 record_printer);
644 }
645
646 TEST_F(MDnsTest, QueryCache) {
647 StrictMock<MockListenerDelegate> delegate_privet;
648
649 RecordParsedCopyContainer record_privet;
650 std::vector<const RecordParsed*> records_from_cache;
651
652 scoped_ptr<MDnsListener> listener_privet = test_factory_->CreateListener(
653 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
654 &delegate_privet);
655
656 ASSERT_TRUE(test_factory_->IsListeningForTests());
657
658 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
659
660 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
661 .Times(Exactly(1))
662 .WillOnce(Invoke(
663 &record_privet,
664 &RecordParsedCopyContainer::SaveWithDummyArg));
665
666 time_system_->RunPendingTasks();
667
668 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
669 record_privet);
670
671 listener_privet->QueryCache(&records_from_cache);
672
673 EXPECT_EQ(1u, records_from_cache.size());
674 EXPECT_EQ("_privet._tcp.local", records_from_cache.front()->name());
675 EXPECT_EQ(dns_protocol::kTypePTR, records_from_cache.front()->type());
676 EXPECT_EQ(dns_protocol::kClassIN, records_from_cache.front()->klass());
677
678 const PtrRecordRdata* ptr_rdata =
679 records_from_cache.front()->rdata<PtrRecordRdata>();
680
681 EXPECT_TRUE(ptr_rdata != NULL);
682
683 EXPECT_EQ("hello._privet._tcp.local",
684 ptr_rdata->ptrdomain());
685 }
686
687 TEST_F(MDnsTest, Query) {
688 StrictMock<MockListenerDelegate> delegate_privet;
689 scoped_ptr<MDnsListener> listener_privet = test_factory_->CreateListener(
690 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
691 &delegate_privet);
692
693 ASSERT_TRUE(listener_privet->SendQuery(false));
694
695 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
696
697 // Active listeners should send queries when created.
698
699 scoped_ptr<MDnsListener> listener_privet2 = test_factory_->CreateListener(
700 dns_protocol::kTypePTR, "_privet._tcp.local", true /*active*/,
701 false /*existing*/, &delegate_privet);
702
703 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
704 }
705
706 TEST_F(MDnsTest, TransactionNoCache) {
707 scoped_ptr<MDnsTransaction> transaction_privet =
708 test_factory_->CreateTransaction(
709 dns_protocol::kTypePTR, "_privet._tcp.local",
710 base::Bind(&MDnsTest::MockableRecordCallback,
711 base::Unretained(this)));
712
713 EXPECT_TRUE(test_factory_->IsListeningForTests());
714
715 RecordParsedCopyContainer record_privet;
716
717 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
718
719 EXPECT_CALL(*this, MockableRecordCallback(kMDnsTransactionSuccess, _))
720 .Times(Exactly(1))
721 .WillOnce(Invoke(&record_privet,
722 &RecordParsedCopyContainer::SaveWithDummyArg));
723
724 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
725
726 time_system_->RunPendingTasks();
727
728 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
729 record_privet);
730
731 EXPECT_FALSE(test_factory_->IsListeningForTests());
732 }
733
734 TEST_F(MDnsTest, TransactionWithCache) {
735 // Listener to force the factory to listen
736 StrictMock<MockListenerDelegate> delegate_irrelevant;
737 scoped_ptr<MDnsListener> listener_irrelevant = test_factory_->CreateListener(
738 dns_protocol::kTypeA, "codereview.chromium.local", false, false,
739 &delegate_irrelevant);
740
741 EXPECT_TRUE(test_factory_->IsListeningForTests());
742
743 SendPacket(kSamplePacket1, sizeof(kSamplePacket1));
744
745 time_system_->RunPendingTasks();
746
747 RecordParsedCopyContainer record_privet;
748
749 EXPECT_CALL(*this, MockableRecordCallback(kMDnsTransactionSuccess, _))
750 .WillOnce(Invoke(&record_privet,
751 &RecordParsedCopyContainer::SaveWithDummyArg));
752
753 scoped_ptr<MDnsTransaction> transaction_privet =
754 test_factory_->CreateTransaction(
755 dns_protocol::kTypePTR, "_privet._tcp.local",
756 base::Bind(&MDnsTest::MockableRecordCallback,
757 base::Unretained(this)));
758
759 // "Expect no packet"?
760
761 time_system_->RunPendingTasks();
762
763 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
764 record_privet);
765 }
766
767 TEST_F(MDnsTest, AdditionalRecords) {
768 StrictMock<MockListenerDelegate> delegate_privet;
769
770 RecordParsedCopyContainer record_privet;
771
772 scoped_ptr<MDnsListener> listener_privet = test_factory_->CreateListener(
773 dns_protocol::kTypePTR, "_privet._tcp.local", false, false,
774 &delegate_privet);
775
776 ASSERT_TRUE(test_factory_->IsListeningForTests());
777
778 // Send the same packet twice to ensure no records are double-counted.
779
780 SendPacket(kSamplePacketAdditionalOnly, sizeof(kSamplePacket1));
781
782 EXPECT_CALL(delegate_privet, OnRecordUpdate(kMDnsRecordAdded, _))
783 .Times(Exactly(1))
784 .WillOnce(Invoke(
785 &record_privet,
786 &RecordParsedCopyContainer::SaveWithDummyArg));
787
788 time_system_->RunPendingTasks();
789
790 ExpectPtrRecord("_privet._tcp.local", "hello._privet._tcp.local",
791 record_privet);
792 }
793
794 TEST_F(MDnsTest, TransactionTimeout) {
795 scoped_ptr<MDnsTransaction> transaction_privet =
796 test_factory_->CreateTransaction(
797 dns_protocol::kTypePTR, "_privet._tcp.local",
798 base::Bind(&MDnsTest::MockableRecordCallback,
799 base::Unretained(this)));
800
801 EXPECT_TRUE(test_factory_->IsListeningForTests());
802
803 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
804
805 EXPECT_CALL(*this, MockableRecordCallback(kMDnsTransactionTimeout, NULL))
806 .Times(Exactly(1));
807
808 time_system_->SetNow(time_system_->Now() + base::TimeDelta::FromMinutes(5));
809
810 time_system_->RunPendingTasks();
811
812 EXPECT_FALSE(test_factory_->IsListeningForTests());
813 }
814
815 TEST_F(MDnsTest, TransactionReentrantDelete) {
816 transaction_ = test_factory_->CreateTransaction(
817 dns_protocol::kTypePTR, "_privet._tcp.local",
818 base::Bind(&MDnsTest::MockableRecordCallback,
819 base::Unretained(this)));
820
821 EXPECT_TRUE(test_factory_->IsListeningForTests());
822
823 ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
824
825 EXPECT_CALL(*this, MockableRecordCallback(kMDnsTransactionTimeout, NULL))
826 .Times(Exactly(1))
827 .WillOnce(InvokeWithoutArgs(this, &MDnsTest::DeleteTransaction));
828
829 time_system_->SetNow(time_system_->Now() + base::TimeDelta::FromMinutes(5));
830
831 time_system_->RunPendingTasks();
832
833 EXPECT_EQ(NULL, transaction_.get());
834
835 EXPECT_FALSE(test_factory_->IsListeningForTests());
836 }
837
838 } // namespace
839
840 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698