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"
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"
35 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
40 // part label, part pointer, "bar.example.com"
44 // all pointer to "bar.example.com", 2 jumps
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.
57 EXPECT_EQ(0x1u
, parser
.ReadName(data
+ 0x10, &out
));
60 EXPECT_EQ(0x6u
, parser
.ReadName(data
+ 0x11, &out
));
61 EXPECT_EQ("bar.example.com", out
);
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
82 // pointer offset beyond packet
87 // incorrect label type (currently supports only direct and pointer)
89 // truncated name (missing root label)
93 DnsRecordParser
parser(data
, sizeof(data
), 0);
94 ASSERT_TRUE(parser
.IsValid());
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',
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
118 0x03, 'b', 'a', 'r', // compressed owner name
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
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
[] = {
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
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',
179 0x00, 0x01, // TYPE is A.
180 0x00, 0x01, // CLASS is IN.
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.
188 0x00, 0x12, // RDLENGTH is 18 bytes.
189 // ghs.l.google.com in DNS format.
192 0x06, 'g', 'o', 'o', 'g', 'l', 'e',
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.
202 0x00, 0x04, // RDLENGTH is 4 bytes.
203 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
208 memcpy(resp
.io_buffer()->data(), response_data
, sizeof(response_data
));
211 EXPECT_FALSE(resp
.InitParse(query
->io_buffer()->size() - 1, *query
));
212 EXPECT_FALSE(resp
.IsValid());
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
) {
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
[] = {
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
287 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
288 0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
291 0x00, 0x01, // TYPE is A.
292 0x00, 0x01, // CLASS is IN.
293 0x00, 0x00, // TTL (4 bytes) is 53 seconds.
295 0x00, 0x04, // RDLENGTH is 4 bytes.
296 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
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
[] = {
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
334 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
335 0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
338 0x00, 0x01, // TYPE is A.
339 0x00, 0x01, // CLASS is IN.
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.
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.
353 0x00, 0x04, // RDLENGTH is 4 bytes.
354 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
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
[] = {
385 0x81, 0x80, // Standard query response, RA, no error
386 0x00, 0x00, // No question
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
{
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
;
416 kT0ResponseDatagram
, arraysize(kT0ResponseDatagram
),
417 kT0IpAddresses
, arraysize(kT0IpAddresses
),
423 kT1ResponseDatagram
, arraysize(kT1ResponseDatagram
),
424 kT1IpAddresses
, arraysize(kT1IpAddresses
),
430 kT2ResponseDatagram
, arraysize(kT2ResponseDatagram
),
431 kT2IpAddresses
, arraysize(kT2IpAddresses
),
437 kT3ResponseDatagram
, arraysize(kT3ResponseDatagram
),
438 kT3IpAddresses
, arraysize(kT3IpAddresses
),
444 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(cases
); ++i
) {
445 const TestCase
& t
= cases
[i
];
446 DnsResponse
response(t
.response_data
, t
.response_size
, t
.query_size
);
447 AddressList addr_list
;
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,
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
{
547 DnsResponse::Result expected_result
;
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_UNSAFE(cases
); ++i
) {
569 const TestCase
& t
= cases
[i
];
571 DnsResponse
response(t
.data
, t
.size
, kQuerySize
);
572 AddressList addr_list
;
574 EXPECT_EQ(t
.expected_result
,
575 response
.ParseToAddressList(&addr_list
, &ttl
));