- add sources.
[platform/framework/web/crosswalk.git] / src / net / dns / dns_response_unittest.cc
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.
4
5 #include "net/dns/dns_response.h"
6
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"
15
16 namespace net {
17
18 namespace {
19
20 TEST(DnsRecordParserTest, Constructor) {
21   const char data[] = { 0 };
22
23   EXPECT_FALSE(DnsRecordParser().IsValid());
24   EXPECT_TRUE(DnsRecordParser(data, 1, 0).IsValid());
25   EXPECT_TRUE(DnsRecordParser(data, 1, 1).IsValid());
26
27   EXPECT_FALSE(DnsRecordParser(data, 1, 0).AtEnd());
28   EXPECT_TRUE(DnsRecordParser(data, 1, 1).AtEnd());
29 }
30
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
47   };
48
49   std::string out;
50   DnsRecordParser parser(data, sizeof(data), 0);
51   ASSERT_TRUE(parser.IsValid());
52
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);
65
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));
71
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));
75 }
76
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',
91   };
92
93   DnsRecordParser parser(data, sizeof(data), 0);
94   ASSERT_TRUE(parser.IsValid());
95
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));
103 }
104
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
125   };
126
127   std::string out;
128   DnsRecordParser parser(data, sizeof(data), 0);
129
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());
140
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());
149
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));
155 }
156
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));
163
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
172
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.
181
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,
195
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,
205   };
206
207   DnsResponse resp;
208   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
209
210   // Reject too short.
211   EXPECT_FALSE(resp.InitParse(query->io_buffer()->size() - 1, *query));
212   EXPECT_FALSE(resp.IsValid());
213
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());
218
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());
224
225   // Accept matching question.
226   EXPECT_TRUE(resp.InitParse(sizeof(response_data), *query));
227   EXPECT_TRUE(resp.IsValid());
228
229   // Check header access.
230   EXPECT_EQ(0x8180, resp.flags());
231   EXPECT_EQ(0x0, resp.rcode());
232   EXPECT_EQ(2u, resp.answer_count());
233
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());
238
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));
246 }
247
248 TEST(DnsResponseTest, InitParseWithoutQuery) {
249   DnsResponse resp;
250   memcpy(resp.io_buffer()->data(), kT0ResponseDatagram,
251          sizeof(kT0ResponseDatagram));
252
253   // Accept matching question.
254   EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(kT0ResponseDatagram)));
255   EXPECT_TRUE(resp.IsValid());
256
257   // Check header access.
258   EXPECT_EQ(0x8180, resp.flags());
259   EXPECT_EQ(0x0, resp.rcode());
260   EXPECT_EQ(kT0RecordCount, resp.answer_count());
261
262   // Check question access.
263   EXPECT_EQ(kT0Qtype, resp.qtype());
264   EXPECT_EQ(kT0HostName, resp.GetDottedName());
265
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));
271   }
272   EXPECT_TRUE(parser.AtEnd());
273   EXPECT_FALSE(parser.ReadRecord(&record));
274 }
275
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
285
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,
298   };
299
300   DnsResponse resp;
301   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
302
303   EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
304
305   // Check header access.
306   EXPECT_EQ(0x8180, resp.flags());
307   EXPECT_EQ(0x0, resp.rcode());
308   EXPECT_EQ(0x1u, resp.answer_count());
309
310   DnsResourceRecord record;
311   DnsRecordParser parser = resp.Parser();
312
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);
318
319   EXPECT_TRUE(parser.AtEnd());
320   EXPECT_FALSE(parser.ReadRecord(&record));
321 }
322
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
332
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.
340
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.
346
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,
356   };
357
358   DnsResponse resp;
359   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
360
361   EXPECT_TRUE(resp.InitParseWithoutQuery(sizeof(response_data)));
362
363   // Check header access.
364   EXPECT_EQ(0x8180, resp.flags());
365   EXPECT_EQ(0x0, resp.rcode());
366   EXPECT_EQ(0x01u, resp.answer_count());
367
368   DnsResourceRecord record;
369   DnsRecordParser parser = resp.Parser();
370
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);
376
377   EXPECT_TRUE(parser.AtEnd());
378   EXPECT_FALSE(parser.ReadRecord(&record));
379 }
380
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
387   };
388
389   DnsResponse resp;
390   memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
391
392   EXPECT_FALSE(resp.InitParseWithoutQuery(sizeof(response_data)));
393 }
394
395 void VerifyAddressList(const std::vector<const char*>& ip_addresses,
396                        const AddressList& addrlist) {
397   ASSERT_EQ(ip_addresses.size(), addrlist.size());
398
399   for (size_t i = 0; i < addrlist.size(); ++i) {
400     EXPECT_EQ(ip_addresses[i], addrlist[i].ToStringWithoutPort());
401   }
402 }
403
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[] = {
414       {
415         kT0QuerySize,
416         kT0ResponseDatagram, arraysize(kT0ResponseDatagram),
417         kT0IpAddresses, arraysize(kT0IpAddresses),
418         kT0CanonName,
419         kT0TTL,
420       },
421       {
422         kT1QuerySize,
423         kT1ResponseDatagram, arraysize(kT1ResponseDatagram),
424         kT1IpAddresses, arraysize(kT1IpAddresses),
425         kT1CanonName,
426         kT1TTL,
427       },
428       {
429         kT2QuerySize,
430         kT2ResponseDatagram, arraysize(kT2ResponseDatagram),
431         kT2IpAddresses, arraysize(kT2IpAddresses),
432         kT2CanonName,
433         kT2TTL,
434       },
435       {
436         kT3QuerySize,
437         kT3ResponseDatagram, arraysize(kT3ResponseDatagram),
438         kT3IpAddresses, arraysize(kT3IpAddresses),
439         kT3CanonName,
440         kT3TTL,
441       },
442   };
443
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;
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);
457   }
458 }
459
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.
468 };
469
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.
478 };
479
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,
488 };
489
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,
504 };
505
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,
514 };
515
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,
527 };
528
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,
541 };
542
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 },
564   };
565
566   const size_t kQuerySize = 12 + 7;
567
568   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
569     const TestCase& t = cases[i];
570
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));
576   }
577 }
578
579 }  // namespace
580
581 }  // namespace net