Chromecast: adds class to help record complex histograms.
[chromium-blink-merge.git] / net / dns / dns_response_unittest.cc
blob6ecfac499223f02fc3bdf51dec930fcc2d366362
1 // Copyright (c) 2012 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 "net/dns/dns_response.h"
7 #include "base/time/time.h"
8 #include "net/base/address_list.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_util.h"
11 #include "net/dns/dns_protocol.h"
12 #include "net/dns/dns_query.h"
13 #include "net/dns/dns_test_util.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace net {
18 namespace {
20 TEST(DnsRecordParserTest, Constructor) {
21 const char data[] = { 0 };
23 EXPECT_FALSE(DnsRecordParser().IsValid());
24 EXPECT_TRUE(DnsRecordParser(data, 1, 0).IsValid());
25 EXPECT_TRUE(DnsRecordParser(data, 1, 1).IsValid());
27 EXPECT_FALSE(DnsRecordParser(data, 1, 0).AtEnd());
28 EXPECT_TRUE(DnsRecordParser(data, 1, 1).AtEnd());
31 TEST(DnsRecordParserTest, ReadName) {
32 const uint8 data[] = {
33 // all labels "foo.example.com"
34 0x03, 'f', 'o', 'o',
35 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
36 0x03, 'c', 'o', 'm',
37 // byte 0x10
38 0x00,
39 // byte 0x11
40 // part label, part pointer, "bar.example.com"
41 0x03, 'b', 'a', 'r',
42 0xc0, 0x04,
43 // byte 0x17
44 // all pointer to "bar.example.com", 2 jumps
45 0xc0, 0x11,
46 // byte 0x1a
49 std::string out;
50 DnsRecordParser parser(data, sizeof(data), 0);
51 ASSERT_TRUE(parser.IsValid());
53 EXPECT_EQ(0x11u, parser.ReadName(data + 0x00, &out));
54 EXPECT_EQ("foo.example.com", out);
55 // Check that the last "." is never stored.
56 out.clear();
57 EXPECT_EQ(0x1u, parser.ReadName(data + 0x10, &out));
58 EXPECT_EQ("", out);
59 out.clear();
60 EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, &out));
61 EXPECT_EQ("bar.example.com", out);
62 out.clear();
63 EXPECT_EQ(0x2u, parser.ReadName(data + 0x17, &out));
64 EXPECT_EQ("bar.example.com", out);
66 // Parse name without storing it.
67 EXPECT_EQ(0x11u, parser.ReadName(data + 0x00, NULL));
68 EXPECT_EQ(0x1u, parser.ReadName(data + 0x10, NULL));
69 EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, NULL));
70 EXPECT_EQ(0x2u, parser.ReadName(data + 0x17, NULL));
72 // Check that it works even if initial position is different.
73 parser = DnsRecordParser(data, sizeof(data), 0x12);
74 EXPECT_EQ(0x6u, parser.ReadName(data + 0x11, NULL));
77 TEST(DnsRecordParserTest, ReadNameFail) {
78 const uint8 data[] = {
79 // label length beyond packet
80 0x30, 'x', 'x',
81 0x00,
82 // pointer offset beyond packet
83 0xc0, 0x20,
84 // pointer loop
85 0xc0, 0x08,
86 0xc0, 0x06,
87 // incorrect label type (currently supports only direct and pointer)
88 0x80, 0x00,
89 // truncated name (missing root label)
90 0x02, 'x', 'x',
93 DnsRecordParser parser(data, sizeof(data), 0);
94 ASSERT_TRUE(parser.IsValid());
96 std::string out;
97 EXPECT_EQ(0u, parser.ReadName(data + 0x00, &out));
98 EXPECT_EQ(0u, parser.ReadName(data + 0x04, &out));
99 EXPECT_EQ(0u, parser.ReadName(data + 0x08, &out));
100 EXPECT_EQ(0u, parser.ReadName(data + 0x0a, &out));
101 EXPECT_EQ(0u, parser.ReadName(data + 0x0c, &out));
102 EXPECT_EQ(0u, parser.ReadName(data + 0x0e, &out));
105 TEST(DnsRecordParserTest, ReadRecord) {
106 const uint8 data[] = {
107 // Type CNAME record.
108 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
109 0x03, 'c', 'o', 'm',
110 0x00,
111 0x00, 0x05, // TYPE is CNAME.
112 0x00, 0x01, // CLASS is IN.
113 0x00, 0x01, 0x24, 0x74, // TTL is 0x00012474.
114 0x00, 0x06, // RDLENGTH is 6 bytes.
115 0x03, 'f', 'o', 'o', // compressed name in record
116 0xc0, 0x00,
117 // Type A record.
118 0x03, 'b', 'a', 'r', // compressed owner name
119 0xc0, 0x00,
120 0x00, 0x01, // TYPE is A.
121 0x00, 0x01, // CLASS is IN.
122 0x00, 0x20, 0x13, 0x55, // TTL is 0x00201355.
123 0x00, 0x04, // RDLENGTH is 4 bytes.
124 0x7f, 0x02, 0x04, 0x01, // IP is 127.2.4.1
127 std::string out;
128 DnsRecordParser parser(data, sizeof(data), 0);
130 DnsResourceRecord record;
131 EXPECT_TRUE(parser.ReadRecord(&record));
132 EXPECT_EQ("example.com", record.name);
133 EXPECT_EQ(dns_protocol::kTypeCNAME, record.type);
134 EXPECT_EQ(dns_protocol::kClassIN, record.klass);
135 EXPECT_EQ(0x00012474u, record.ttl);
136 EXPECT_EQ(6u, record.rdata.length());
137 EXPECT_EQ(6u, parser.ReadName(record.rdata.data(), &out));
138 EXPECT_EQ("foo.example.com", out);
139 EXPECT_FALSE(parser.AtEnd());
141 EXPECT_TRUE(parser.ReadRecord(&record));
142 EXPECT_EQ("bar.example.com", record.name);
143 EXPECT_EQ(dns_protocol::kTypeA, record.type);
144 EXPECT_EQ(dns_protocol::kClassIN, record.klass);
145 EXPECT_EQ(0x00201355u, record.ttl);
146 EXPECT_EQ(4u, record.rdata.length());
147 EXPECT_EQ(base::StringPiece("\x7f\x02\x04\x01"), record.rdata);
148 EXPECT_TRUE(parser.AtEnd());
150 // Test truncated record.
151 parser = DnsRecordParser(data, sizeof(data) - 2, 0);
152 EXPECT_TRUE(parser.ReadRecord(&record));
153 EXPECT_FALSE(parser.AtEnd());
154 EXPECT_FALSE(parser.ReadRecord(&record));
157 TEST(DnsResponseTest, InitParse) {
158 // This includes \0 at the end.
159 const char qname_data[] = "\x0A""codereview""\x08""chromium""\x03""org";
160 const base::StringPiece qname(qname_data, sizeof(qname_data));
161 // Compilers want to copy when binding temporary to const &, so must use heap.
162 scoped_ptr<DnsQuery> query(new DnsQuery(0xcafe, qname, dns_protocol::kTypeA));
164 const uint8 response_data[] = {
165 // Header
166 0xca, 0xfe, // ID
167 0x81, 0x80, // Standard query response, RA, no error
168 0x00, 0x01, // 1 question
169 0x00, 0x02, // 2 RRs (answers)
170 0x00, 0x00, // 0 authority RRs
171 0x00, 0x00, // 0 additional RRs
173 // Question
174 // This part is echoed back from the respective query.
175 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
176 0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
177 0x03, 'o', 'r', 'g',
178 0x00,
179 0x00, 0x01, // TYPE is A.
180 0x00, 0x01, // CLASS is IN.
182 // Answer 1
183 0xc0, 0x0c, // NAME is a pointer to name in Question section.
184 0x00, 0x05, // TYPE is CNAME.
185 0x00, 0x01, // CLASS is IN.
186 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
187 0x24, 0x74,
188 0x00, 0x12, // RDLENGTH is 18 bytes.
189 // ghs.l.google.com in DNS format.
190 0x03, 'g', 'h', 's',
191 0x01, 'l',
192 0x06, 'g', 'o', 'o', 'g', 'l', 'e',
193 0x03, 'c', 'o', 'm',
194 0x00,
196 // Answer 2
197 0xc0, 0x35, // NAME is a pointer to name in Answer 1.
198 0x00, 0x01, // TYPE is A.
199 0x00, 0x01, // CLASS is IN.
200 0x00, 0x00, // TTL (4 bytes) is 53 seconds.
201 0x00, 0x35,
202 0x00, 0x04, // RDLENGTH is 4 bytes.
203 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
204 0x5f, 0x79,
207 DnsResponse resp;
208 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
210 // Reject too short.
211 EXPECT_FALSE(resp.InitParse(query->io_buffer()->size() - 1, *query));
212 EXPECT_FALSE(resp.IsValid());
214 // Reject wrong id.
215 scoped_ptr<DnsQuery> other_query(query->CloneWithNewId(0xbeef));
216 EXPECT_FALSE(resp.InitParse(sizeof(response_data), *other_query));
217 EXPECT_FALSE(resp.IsValid());
219 // Reject wrong question.
220 scoped_ptr<DnsQuery> wrong_query(
221 new DnsQuery(0xcafe, qname, dns_protocol::kTypeCNAME));
222 EXPECT_FALSE(resp.InitParse(sizeof(response_data), *wrong_query));
223 EXPECT_FALSE(resp.IsValid());
225 // Accept matching question.
226 EXPECT_TRUE(resp.InitParse(sizeof(response_data), *query));
227 EXPECT_TRUE(resp.IsValid());
229 // Check header access.
230 EXPECT_EQ(0x8180, resp.flags());
231 EXPECT_EQ(0x0, resp.rcode());
232 EXPECT_EQ(2u, resp.answer_count());
234 // Check question access.
235 EXPECT_EQ(query->qname(), resp.qname());
236 EXPECT_EQ(query->qtype(), resp.qtype());
237 EXPECT_EQ("codereview.chromium.org", resp.GetDottedName());
239 DnsResourceRecord record;
240 DnsRecordParser parser = resp.Parser();
241 EXPECT_TRUE(parser.ReadRecord(&record));
242 EXPECT_FALSE(parser.AtEnd());
243 EXPECT_TRUE(parser.ReadRecord(&record));
244 EXPECT_TRUE(parser.AtEnd());
245 EXPECT_FALSE(parser.ReadRecord(&record));
248 TEST(DnsResponseTest, InitParseWithoutQuery) {
249 DnsResponse resp;
250 memcpy(resp.io_buffer()->data(), kT0ResponseDatagram,
251 sizeof(kT0ResponseDatagram));
253 // Accept matching question.
254 EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(kT0ResponseDatagram)));
255 EXPECT_TRUE(resp.IsValid());
257 // Check header access.
258 EXPECT_EQ(0x8180, resp.flags());
259 EXPECT_EQ(0x0, resp.rcode());
260 EXPECT_EQ(kT0RecordCount, resp.answer_count());
262 // Check question access.
263 EXPECT_EQ(kT0Qtype, resp.qtype());
264 EXPECT_EQ(kT0HostName, resp.GetDottedName());
266 DnsResourceRecord record;
267 DnsRecordParser parser = resp.Parser();
268 for (unsigned i = 0; i < kT0RecordCount; i ++) {
269 EXPECT_FALSE(parser.AtEnd());
270 EXPECT_TRUE(parser.ReadRecord(&record));
272 EXPECT_TRUE(parser.AtEnd());
273 EXPECT_FALSE(parser.ReadRecord(&record));
276 TEST(DnsResponseTest, InitParseWithoutQueryNoQuestions) {
277 const uint8 response_data[] = {
278 // Header
279 0xca, 0xfe, // ID
280 0x81, 0x80, // Standard query response, RA, no error
281 0x00, 0x00, // No question
282 0x00, 0x01, // 2 RRs (answers)
283 0x00, 0x00, // 0 authority RRs
284 0x00, 0x00, // 0 additional RRs
286 // Answer 1
287 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
288 0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
289 0x03, 'o', 'r', 'g',
290 0x00,
291 0x00, 0x01, // TYPE is A.
292 0x00, 0x01, // CLASS is IN.
293 0x00, 0x00, // TTL (4 bytes) is 53 seconds.
294 0x00, 0x35,
295 0x00, 0x04, // RDLENGTH is 4 bytes.
296 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
297 0x5f, 0x79,
300 DnsResponse resp;
301 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
303 EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
305 // Check header access.
306 EXPECT_EQ(0x8180, resp.flags());
307 EXPECT_EQ(0x0, resp.rcode());
308 EXPECT_EQ(0x1u, resp.answer_count());
310 DnsResourceRecord record;
311 DnsRecordParser parser = resp.Parser();
313 EXPECT_FALSE(parser.AtEnd());
314 EXPECT_TRUE(parser.ReadRecord(&record));
315 EXPECT_EQ("codereview.chromium.org", record.name);
316 EXPECT_EQ(0x00000035u, record.ttl);
317 EXPECT_EQ(dns_protocol::kTypeA, record.type);
319 EXPECT_TRUE(parser.AtEnd());
320 EXPECT_FALSE(parser.ReadRecord(&record));
323 TEST(DnsResponseTest, InitParseWithoutQueryTwoQuestions) {
324 const uint8 response_data[] = {
325 // Header
326 0xca, 0xfe, // ID
327 0x81, 0x80, // Standard query response, RA, no error
328 0x00, 0x02, // 2 questions
329 0x00, 0x01, // 2 RRs (answers)
330 0x00, 0x00, // 0 authority RRs
331 0x00, 0x00, // 0 additional RRs
333 // Question 1
334 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
335 0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
336 0x03, 'o', 'r', 'g',
337 0x00,
338 0x00, 0x01, // TYPE is A.
339 0x00, 0x01, // CLASS is IN.
341 // Question 2
342 0x0b, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', '2',
343 0xc0, 0x18, // pointer to "chromium.org"
344 0x00, 0x01, // TYPE is A.
345 0x00, 0x01, // CLASS is IN.
347 // Answer 1
348 0xc0, 0x0c, // NAME is a pointer to name in Question section.
349 0x00, 0x01, // TYPE is A.
350 0x00, 0x01, // CLASS is IN.
351 0x00, 0x00, // TTL (4 bytes) is 53 seconds.
352 0x00, 0x35,
353 0x00, 0x04, // RDLENGTH is 4 bytes.
354 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
355 0x5f, 0x79,
358 DnsResponse resp;
359 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
361 EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
363 // Check header access.
364 EXPECT_EQ(0x8180, resp.flags());
365 EXPECT_EQ(0x0, resp.rcode());
366 EXPECT_EQ(0x01u, resp.answer_count());
368 DnsResourceRecord record;
369 DnsRecordParser parser = resp.Parser();
371 EXPECT_FALSE(parser.AtEnd());
372 EXPECT_TRUE(parser.ReadRecord(&record));
373 EXPECT_EQ("codereview.chromium.org", record.name);
374 EXPECT_EQ(0x35u, record.ttl);
375 EXPECT_EQ(dns_protocol::kTypeA, record.type);
377 EXPECT_TRUE(parser.AtEnd());
378 EXPECT_FALSE(parser.ReadRecord(&record));
381 TEST(DnsResponseTest, InitParseWithoutQueryPacketTooShort) {
382 const uint8 response_data[] = {
383 // Header
384 0xca, 0xfe, // ID
385 0x81, 0x80, // Standard query response, RA, no error
386 0x00, 0x00, // No question
389 DnsResponse resp;
390 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
392 EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(response_data)));
395 void VerifyAddressList(const std::vector<const char*>& ip_addresses,
396 const AddressList& addrlist) {
397 ASSERT_EQ(ip_addresses.size(), addrlist.size());
399 for (size_t i = 0; i < addrlist.size(); ++i) {
400 EXPECT_EQ(ip_addresses[i], addrlist[i].ToStringWithoutPort());
404 TEST(DnsResponseTest, ParseToAddressList) {
405 const struct TestCase {
406 size_t query_size;
407 const uint8* response_data;
408 size_t response_size;
409 const char* const* expected_addresses;
410 size_t num_expected_addresses;
411 const char* expected_cname;
412 int expected_ttl_sec;
413 } cases[] = {
415 kT0QuerySize,
416 kT0ResponseDatagram, arraysize(kT0ResponseDatagram),
417 kT0IpAddresses, arraysize(kT0IpAddresses),
418 kT0CanonName,
419 kT0TTL,
422 kT1QuerySize,
423 kT1ResponseDatagram, arraysize(kT1ResponseDatagram),
424 kT1IpAddresses, arraysize(kT1IpAddresses),
425 kT1CanonName,
426 kT1TTL,
429 kT2QuerySize,
430 kT2ResponseDatagram, arraysize(kT2ResponseDatagram),
431 kT2IpAddresses, arraysize(kT2IpAddresses),
432 kT2CanonName,
433 kT2TTL,
436 kT3QuerySize,
437 kT3ResponseDatagram, arraysize(kT3ResponseDatagram),
438 kT3IpAddresses, arraysize(kT3IpAddresses),
439 kT3CanonName,
440 kT3TTL,
444 for (size_t i = 0; i < arraysize(cases); ++i) {
445 const TestCase& t = cases[i];
446 DnsResponse response(t.response_data, t.response_size, t.query_size);
447 AddressList addr_list;
448 base::TimeDelta ttl;
449 EXPECT_EQ(DnsResponse::DNS_PARSE_OK,
450 response.ParseToAddressList(&addr_list, &ttl));
451 std::vector<const char*> expected_addresses(
452 t.expected_addresses,
453 t.expected_addresses + t.num_expected_addresses);
454 VerifyAddressList(expected_addresses, addr_list);
455 EXPECT_EQ(t.expected_cname, addr_list.canonical_name());
456 EXPECT_EQ(base::TimeDelta::FromSeconds(t.expected_ttl_sec), ttl);
460 const uint8 kResponseTruncatedRecord[] = {
461 // Header: 1 question, 1 answer RR
462 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
463 // Question: name = 'a', type = A (0x1)
464 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
465 // Answer: name = 'a', type = A, TTL = 0xFF, RDATA = 10.10.10.10
466 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
467 0x00, 0x04, 0x0A, 0x0A, 0x0A, // Truncated RDATA.
470 const uint8 kResponseTruncatedCNAME[] = {
471 // Header: 1 question, 1 answer RR
472 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
473 // Question: name = 'a', type = A (0x1)
474 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
475 // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'foo' (truncated)
476 0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
477 0x00, 0x03, 0x03, 'f', 'o', // Truncated name.
480 const uint8 kResponseNameMismatch[] = {
481 // Header: 1 question, 1 answer RR
482 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
483 // Question: name = 'a', type = A (0x1)
484 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
485 // Answer: name = 'b', type = A, TTL = 0xFF, RDATA = 10.10.10.10
486 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
487 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
490 const uint8 kResponseNameMismatchInChain[] = {
491 // Header: 1 question, 3 answer RR
492 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
493 // Question: name = 'a', type = A (0x1)
494 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
495 // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'b'
496 0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
497 0x00, 0x03, 0x01, 'b', 0x00,
498 // Answer: name = 'b', type = A, TTL = 0xFF, RDATA = 10.10.10.10
499 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
500 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
501 // Answer: name = 'c', type = A, TTL = 0xFF, RDATA = 10.10.10.11
502 0x01, 'c', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
503 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0B,
506 const uint8 kResponseSizeMismatch[] = {
507 // Header: 1 answer RR
508 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
509 // Question: name = 'a', type = AAAA (0x1c)
510 0x01, 'a', 0x00, 0x00, 0x1c, 0x00, 0x01,
511 // Answer: name = 'a', type = AAAA, TTL = 0xFF, RDATA = 10.10.10.10
512 0x01, 'a', 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
513 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
516 const uint8 kResponseCNAMEAfterAddress[] = {
517 // Header: 2 answer RR
518 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
519 // Question: name = 'a', type = A (0x1)
520 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
521 // Answer: name = 'a', type = A, TTL = 0xFF, RDATA = 10.10.10.10.
522 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
523 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
524 // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'b'
525 0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
526 0x00, 0x03, 0x01, 'b', 0x00,
529 const uint8 kResponseNoAddresses[] = {
530 // Header: 1 question, 1 answer RR, 1 authority RR
531 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
532 // Question: name = 'a', type = A (0x1)
533 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
534 // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'b'
535 0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
536 0x00, 0x03, 0x01, 'b', 0x00,
537 // Authority section
538 // Answer: name = 'b', type = A, TTL = 0xFF, RDATA = 10.10.10.10
539 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
540 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
543 TEST(DnsResponseTest, ParseToAddressListFail) {
544 const struct TestCase {
545 const uint8* data;
546 size_t size;
547 DnsResponse::Result expected_result;
548 } cases[] = {
549 { kResponseTruncatedRecord, arraysize(kResponseTruncatedRecord),
550 DnsResponse::DNS_MALFORMED_RESPONSE },
551 { kResponseTruncatedCNAME, arraysize(kResponseTruncatedCNAME),
552 DnsResponse::DNS_MALFORMED_CNAME },
553 { kResponseNameMismatch, arraysize(kResponseNameMismatch),
554 DnsResponse::DNS_NAME_MISMATCH },
555 { kResponseNameMismatchInChain, arraysize(kResponseNameMismatchInChain),
556 DnsResponse::DNS_NAME_MISMATCH },
557 { kResponseSizeMismatch, arraysize(kResponseSizeMismatch),
558 DnsResponse::DNS_SIZE_MISMATCH },
559 { kResponseCNAMEAfterAddress, arraysize(kResponseCNAMEAfterAddress),
560 DnsResponse::DNS_CNAME_AFTER_ADDRESS },
561 // Not actually a failure, just an empty result.
562 { kResponseNoAddresses, arraysize(kResponseNoAddresses),
563 DnsResponse::DNS_PARSE_OK },
566 const size_t kQuerySize = 12 + 7;
568 for (size_t i = 0; i < arraysize(cases); ++i) {
569 const TestCase& t = cases[i];
571 DnsResponse response(t.data, t.size, kQuerySize);
572 AddressList addr_list;
573 base::TimeDelta ttl;
574 EXPECT_EQ(t.expected_result,
575 response.ParseToAddressList(&addr_list, &ttl));
579 } // namespace
581 } // namespace net