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"
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 void VerifyAddressList(const std::vector
<const char*>& ip_addresses
,
382 const AddressList
& addrlist
) {
383 ASSERT_EQ(ip_addresses
.size(), addrlist
.size());
385 for (size_t i
= 0; i
< addrlist
.size(); ++i
) {
386 EXPECT_EQ(ip_addresses
[i
], addrlist
[i
].ToStringWithoutPort());
390 TEST(DnsResponseTest
, ParseToAddressList
) {
391 const struct TestCase
{
393 const uint8
* response_data
;
394 size_t response_size
;
395 const char* const* expected_addresses
;
396 size_t num_expected_addresses
;
397 const char* expected_cname
;
398 int expected_ttl_sec
;
402 kT0ResponseDatagram
, arraysize(kT0ResponseDatagram
),
403 kT0IpAddresses
, arraysize(kT0IpAddresses
),
409 kT1ResponseDatagram
, arraysize(kT1ResponseDatagram
),
410 kT1IpAddresses
, arraysize(kT1IpAddresses
),
416 kT2ResponseDatagram
, arraysize(kT2ResponseDatagram
),
417 kT2IpAddresses
, arraysize(kT2IpAddresses
),
423 kT3ResponseDatagram
, arraysize(kT3ResponseDatagram
),
424 kT3IpAddresses
, arraysize(kT3IpAddresses
),
430 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(cases
); ++i
) {
431 const TestCase
& t
= cases
[i
];
432 DnsResponse
response(t
.response_data
, t
.response_size
, t
.query_size
);
433 AddressList addr_list
;
435 EXPECT_EQ(DnsResponse::DNS_PARSE_OK
,
436 response
.ParseToAddressList(&addr_list
, &ttl
));
437 std::vector
<const char*> expected_addresses(
438 t
.expected_addresses
,
439 t
.expected_addresses
+ t
.num_expected_addresses
);
440 VerifyAddressList(expected_addresses
, addr_list
);
441 EXPECT_EQ(t
.expected_cname
, addr_list
.canonical_name());
442 EXPECT_EQ(base::TimeDelta::FromSeconds(t
.expected_ttl_sec
), ttl
);
446 const uint8 kResponseTruncatedRecord
[] = {
447 // Header: 1 question, 1 answer RR
448 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
449 // Question: name = 'a', type = A (0x1)
450 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
451 // Answer: name = 'a', type = A, TTL = 0xFF, RDATA = 10.10.10.10
452 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
453 0x00, 0x04, 0x0A, 0x0A, 0x0A, // Truncated RDATA.
456 const uint8 kResponseTruncatedCNAME
[] = {
457 // Header: 1 question, 1 answer RR
458 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
459 // Question: name = 'a', type = A (0x1)
460 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
461 // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'foo' (truncated)
462 0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
463 0x00, 0x03, 0x03, 'f', 'o', // Truncated name.
466 const uint8 kResponseNameMismatch
[] = {
467 // Header: 1 question, 1 answer RR
468 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
469 // Question: name = 'a', type = A (0x1)
470 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
471 // Answer: name = 'b', type = A, TTL = 0xFF, RDATA = 10.10.10.10
472 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
473 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
476 const uint8 kResponseNameMismatchInChain
[] = {
477 // Header: 1 question, 3 answer RR
478 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
479 // Question: name = 'a', type = A (0x1)
480 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
481 // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'b'
482 0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
483 0x00, 0x03, 0x01, 'b', 0x00,
484 // Answer: name = 'b', type = A, TTL = 0xFF, RDATA = 10.10.10.10
485 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
486 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
487 // Answer: name = 'c', type = A, TTL = 0xFF, RDATA = 10.10.10.11
488 0x01, 'c', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
489 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0B,
492 const uint8 kResponseSizeMismatch
[] = {
493 // Header: 1 answer RR
494 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
495 // Question: name = 'a', type = AAAA (0x1c)
496 0x01, 'a', 0x00, 0x00, 0x1c, 0x00, 0x01,
497 // Answer: name = 'a', type = AAAA, TTL = 0xFF, RDATA = 10.10.10.10
498 0x01, 'a', 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
499 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
502 const uint8 kResponseCNAMEAfterAddress
[] = {
503 // Header: 2 answer RR
504 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
505 // Question: name = 'a', type = A (0x1)
506 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
507 // Answer: name = 'a', type = A, TTL = 0xFF, RDATA = 10.10.10.10.
508 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
509 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
510 // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'b'
511 0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
512 0x00, 0x03, 0x01, 'b', 0x00,
515 const uint8 kResponseNoAddresses
[] = {
516 // Header: 1 question, 1 answer RR, 1 authority RR
517 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
518 // Question: name = 'a', type = A (0x1)
519 0x01, 'a', 0x00, 0x00, 0x01, 0x00, 0x01,
520 // Answer: name = 'a', type = CNAME, TTL = 0xFF, RDATA = 'b'
521 0x01, 'a', 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
522 0x00, 0x03, 0x01, 'b', 0x00,
524 // Answer: name = 'b', type = A, TTL = 0xFF, RDATA = 10.10.10.10
525 0x01, 'b', 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF,
526 0x00, 0x04, 0x0A, 0x0A, 0x0A, 0x0A,
529 TEST(DnsResponseTest
, ParseToAddressListFail
) {
530 const struct TestCase
{
533 DnsResponse::Result expected_result
;
535 { kResponseTruncatedRecord
, arraysize(kResponseTruncatedRecord
),
536 DnsResponse::DNS_MALFORMED_RESPONSE
},
537 { kResponseTruncatedCNAME
, arraysize(kResponseTruncatedCNAME
),
538 DnsResponse::DNS_MALFORMED_CNAME
},
539 { kResponseNameMismatch
, arraysize(kResponseNameMismatch
),
540 DnsResponse::DNS_NAME_MISMATCH
},
541 { kResponseNameMismatchInChain
, arraysize(kResponseNameMismatchInChain
),
542 DnsResponse::DNS_NAME_MISMATCH
},
543 { kResponseSizeMismatch
, arraysize(kResponseSizeMismatch
),
544 DnsResponse::DNS_SIZE_MISMATCH
},
545 { kResponseCNAMEAfterAddress
, arraysize(kResponseCNAMEAfterAddress
),
546 DnsResponse::DNS_CNAME_AFTER_ADDRESS
},
547 // Not actually a failure, just an empty result.
548 { kResponseNoAddresses
, arraysize(kResponseNoAddresses
),
549 DnsResponse::DNS_PARSE_OK
},
552 const size_t kQuerySize
= 12 + 7;
554 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(cases
); ++i
) {
555 const TestCase
& t
= cases
[i
];
557 DnsResponse
response(t
.data
, t
.size
, kQuerySize
);
558 AddressList addr_list
;
560 EXPECT_EQ(t
.expected_result
,
561 response
.ParseToAddressList(&addr_list
, &ttl
));