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

Side by Side Diff: net/dns/dns_response_unittest.cc

Issue 8762001: Isolates generic DnsClient from AsyncHostResolver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/dns/dns_response.h" 5 #include "net/dns/dns_response.h"
6 6
7 #include "base/bind.h"
8 #include "base/rand_util.h"
9 #include "net/base/dns_util.h"
10 #include "net/base/net_errors.h"
11 #include "net/base/io_buffer.h" 7 #include "net/base/io_buffer.h"
12 #include "net/dns/dns_query.h" 8 #include "net/dns/dns_query.h"
13 #include "testing/gtest/include/gtest/gtest.h" 9 #include "testing/gtest/include/gtest/gtest.h"
14 10
15 namespace net { 11 namespace net {
16 12
17 // DNS response consists of a header followed by a question followed by 13 TEST(DnsRecordParserTest, Constructor) {
18 // answer. Header format, question format and response format are 14 const char data[] = { 0 };
19 // described below. For the meaning of specific fields, please see RFC
20 // 1035.
21 15
22 // Header format. 16 EXPECT_FALSE(DnsRecordParser().IsValid());
23 // 1 1 1 1 1 1 17 EXPECT_TRUE(DnsRecordParser(data, 1, 0).IsValid());
24 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 18 EXPECT_TRUE(DnsRecordParser(data, 1, 1).IsValid());
25 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
26 // | ID |
27 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
28 // |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
29 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
30 // | QDCOUNT |
31 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
32 // | ANCOUNT |
33 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
34 // | NSCOUNT |
35 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
36 // | ARCOUNT |
37 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
38 19
39 // Question format. 20 EXPECT_FALSE(DnsRecordParser(data, 1, 0).AtEnd());
40 // 1 1 1 1 1 1 21 EXPECT_TRUE(DnsRecordParser(data, 1, 1).AtEnd());
41 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 22 }
42 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
43 // | |
44 // / QNAME /
45 // / /
46 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
47 // | QTYPE |
48 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
49 // | QCLASS |
50 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
51 23
52 // Answser format. 24 TEST(DnsRecordParserTest, ParseName) {
53 // 1 1 1 1 1 1 25 const uint8 data[] = {
54 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 26 // all labels "foo.example.com"
55 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 27 0x03, 'f', 'o', 'o',
56 // | | 28 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
57 // / / 29 0x03, 'c', 'o', 'm',
58 // / NAME / 30 // byte 0x10
59 // | | 31 0x00,
60 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 32 // byte 0x11
61 // | TYPE | 33 // part label, part pointer, "bar.example.com"
62 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 34 0x03, 'b', 'a', 'r',
63 // | CLASS | 35 0xc0, 0x04,
64 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 36 // byte 0x17
65 // | TTL | 37 // all pointer to "bar.example.com", 2 jumps
66 // | | 38 0xc0, 0x11,
67 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 39 // byte 0x1a
68 // | RDLENGTH |
69 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
70 // / RDATA /
71 // / /
72 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
73
74 // TODO(agayev): add more thorough tests.
75 TEST(DnsResponseTest, ResponseWithCnameA) {
76 const std::string kQname("\012codereview\010chromium\003org", 25);
77 DnsQuery q1(kQname, kDNS_A, base::Bind(&base::RandInt));
78
79 uint8 id_hi = q1.id() >> 8, id_lo = q1.id() & 0xff;
80
81 uint8 ip[] = { // codereview.chromium.org resolves to
82 0x4a, 0x7d, 0x5f, 0x79 // 74.125.95.121
83 }; 40 };
84 41
85 IPAddressList expected_ips; 42 std::string out;
86 expected_ips.push_back(IPAddressNumber(ip, ip + arraysize(ip))); 43 DnsRecordParser it(data, sizeof(data), 0);
44 ASSERT_TRUE(it.IsValid());
87 45
88 uint8 response_data[] = { 46 EXPECT_EQ(0x11, it.ParseName(data + 0x00, &out));
47 EXPECT_EQ("foo.example.com", out);
48 // check that the last "." is never stored
49 out.clear();
50 EXPECT_EQ(0x1, it.ParseName(data + 0x10, &out));
51 EXPECT_EQ("", out);
52 out.clear();
53 EXPECT_EQ(0x6, it.ParseName(data + 0x11, &out));
54 EXPECT_EQ("bar.example.com", out);
55 out.clear();
56 EXPECT_EQ(0x2, it.ParseName(data + 0x17, &out));
57 EXPECT_EQ("bar.example.com", out);
58
59 // parse name without storing it
60 EXPECT_EQ(0x11, it.ParseName(data + 0x00, NULL));
61 EXPECT_EQ(0x1, it.ParseName(data + 0x10, NULL));
62 EXPECT_EQ(0x6, it.ParseName(data + 0x11, NULL));
63 EXPECT_EQ(0x2, it.ParseName(data + 0x17, NULL));
64
65 // check that it works even if initial position is different
66 it = DnsRecordParser(data, sizeof(data), 0x12);
67 EXPECT_EQ(0x6, it.ParseName(data + 0x11, NULL));
68 }
69
70 TEST(DnsRecordParserTest, ParseNameFail) {
71 const uint8 data[] = {
72 // label length beyond packet
73 0x30, 'x', 'x',
74 0x00,
75 // pointer offset beyond packet
76 0xc0, 0x20,
77 // pointer loop
78 0xc0, 0x0a,
79 0xc0, 0x08,
80 // incorrect label type (currently supports only direct and pointer)
81 0x80, 0x00,
82 // truncated name (missing root label)
83 0x02, 'x', 'x',
84 };
85
86 DnsRecordParser it(data, sizeof(data), 0);
87 ASSERT_TRUE(it.IsValid());
88
89 std::string out;
90 EXPECT_EQ(0, it.ParseName(data + 0x00, &out));
91 EXPECT_EQ(0, it.ParseName(data + 0x04, &out));
92 EXPECT_EQ(0, it.ParseName(data + 0x08, &out));
93 EXPECT_EQ(0, it.ParseName(data + 0x0a, &out));
94 EXPECT_EQ(0, it.ParseName(data + 0x0c, &out));
95 EXPECT_EQ(0, it.ParseName(data + 0x0e, &out));
96 }
97
98 TEST(DnsRecordParserTest, ParseRecord) {
99 const uint8 data[] = {
100 // Type CNAME record.
101 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
102 0x03, 'c', 'o', 'm',
103 0x00,
104 0x00, 0x05, // TYPE is CNAME.
105 0x00, 0x01, // CLASS is IN.
106 0x00, 0x01, 0x24, 0x74, // TTL is 0x00012474.
107 0x00, 0x06, // RDLENGTH is 6 bytes.
108 0x03, 'f', 'o', 'o', // compressed name in record
109 0xc0, 0x00,
110 // Type A record.
111 0x03, 'b', 'a', 'r', // compressed owner name
112 0xc0, 0x00,
113 0x00, 0x01, // TYPE is A.
114 0x00, 0x01, // CLASS is IN.
115 0x00, 0x20, 0x13, 0x55, // TTL is 0x00201355.
116 0x00, 0x04, // RDLENGTH is 4 bytes.
117 0x7f, 0x02, 0x04, 0x01, // IP is 127.2.4.1
118 };
119
120 std::string out;
121 DnsRecordParser it(data, sizeof(data), 0);
122
123 DnsResourceRecord record;
124 EXPECT_TRUE(it.ParseRecord(&record));
125 EXPECT_EQ("example.com", record.name);
126 EXPECT_EQ(dns_protocol::kTypeCNAME, record.type);
127 EXPECT_EQ(dns_protocol::kClassIN, record.klass);
128 EXPECT_EQ(0x00012474u, record.ttl);
129 EXPECT_EQ(6u, record.rdata.length());
130 EXPECT_EQ(6, it.ParseName(record.rdata.data(), &out));
131 EXPECT_EQ("foo.example.com", out);
132 EXPECT_FALSE(it.AtEnd());
133
134 EXPECT_TRUE(it.ParseRecord(&record));
135 EXPECT_EQ("bar.example.com", record.name);
136 EXPECT_EQ(dns_protocol::kTypeA, record.type);
137 EXPECT_EQ(dns_protocol::kClassIN, record.klass);
138 EXPECT_EQ(0x00201355u, record.ttl);
139 EXPECT_EQ(4u, record.rdata.length());
140 EXPECT_EQ(base::StringPiece("\x7f\x02\x04\x01"), record.rdata);
141 EXPECT_TRUE(it.AtEnd());
142
143 // Test truncated record
144 it = DnsRecordParser(data, sizeof(data) - 2, 0);
145 EXPECT_TRUE(it.ParseRecord(&record));
146 EXPECT_FALSE(it.AtEnd());
147 EXPECT_FALSE(it.ParseRecord(&record));
148 }
149
150 TEST(DnsResponseTest, InitParse) {
151 // This includes \0 at the end.
152 const char qname_data[] = "\x0A""codereview""\x08""chromium""\x03""org";
153 const base::StringPiece qname(qname_data, sizeof(qname_data));
154 // Compilers want to copy when binding temporary to const &, so must use heap.
155 scoped_ptr<DnsQuery> query(new DnsQuery(0xcafe, qname, dns_protocol::kTypeA));
156
157 const uint8 response_data[] = {
89 // Header 158 // Header
90 id_hi, id_lo, // ID 159 0xca, 0xfe, // ID
91 0x81, 0x80, // Standard query response, no error 160 0x81, 0x80, // Standard query response, RA, no error
92 0x00, 0x01, // 1 question 161 0x00, 0x01, // 1 question
93 0x00, 0x02, // 2 RRs (answers) 162 0x00, 0x02, // 2 RRs (answers)
94 0x00, 0x00, // 0 authority RRs 163 0x00, 0x00, // 0 authority RRs
95 0x00, 0x00, // 0 additional RRs 164 0x00, 0x00, // 0 additional RRs
96 165
97 // Question 166 // Question
98 0x0a, 0x63, 0x6f, 0x64, // This part is echoed back from the 167 // This part is echoed back from the respective query.
99 0x65, 0x72, 0x65, 0x76, // respective query. 168 0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w',
100 0x69, 0x65, 0x77, 0x08, 169 0x08, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm',
101 0x63, 0x68, 0x72, 0x6f, 170 0x03, 'o', 'r', 'g',
102 0x6d, 0x69, 0x75, 0x6d,
103 0x03, 0x6f, 0x72, 0x67,
104 0x00, 171 0x00,
105 0x00, 0x01, 172 0x00, 0x01, // TYPE is A.
106 0x00, 0x01, 173 0x00, 0x01, // CLASS is IN.
107 174
108 // Answer 1 175 // Answer 1
109 0xc0, 0x0c, // NAME is a pointer to name in Question section. 176 0xc0, 0x0c, // NAME is a pointer to name in Question section.
110 0x00, 0x05, // TYPE is CNAME. 177 0x00, 0x05, // TYPE is CNAME.
111 0x00, 0x01, // CLASS is IN. 178 0x00, 0x01, // CLASS is IN.
112 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. 179 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
113 0x24, 0x74, 180 0x24, 0x74,
114 0x00, 0x12, // RDLENGTH is 18 bytse. 181 0x00, 0x12, // RDLENGTH is 18 bytes.
115 0x03, 0x67, 0x68, 0x73, // ghs.l.google.com in DNS format. 182 // ghs.l.google.com in DNS format.
116 0x01, 0x6c, 0x06, 0x67, 183 0x03, 'g', 'h', 's',
117 0x6f, 0x6f, 0x67, 0x6c, 184 0x01, 'l',
118 0x65, 0x03, 0x63, 0x6f, 185 0x06, 'g', 'o', 'o', 'g', 'l', 'e',
119 0x6d, 0x00, 186 0x03, 'c', 'o', 'm',
187 0x00,
120 188
121 // Answer 2 189 // Answer 2
122 0xc0, 0x35, // NAME is a pointer to name in Question section. 190 0xc0, 0x35, // NAME is a pointer to name in Question section.
123 0x00, 0x01, // TYPE is A. 191 0x00, 0x01, // TYPE is A.
124 0x00, 0x01, // CLASS is IN. 192 0x00, 0x01, // CLASS is IN.
125 0x00, 0x00, // TTL (4 bytes) is 53 seconds. 193 0x00, 0x00, // TTL (4 bytes) is 53 seconds.
126 0x00, 0x35, 194 0x00, 0x35,
127 0x00, 0x04, // RDLENGTH is 4 bytes. 195 0x00, 0x04, // RDLENGTH is 4 bytes.
128 ip[0], ip[1], ip[2], ip[3], // RDATA is the IP. 196 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121
197 0x5f, 0x79,
129 }; 198 };
130 199
131 // Create a response object and simulate reading into it. 200 DnsResponse resp;
132 DnsResponse r1(&q1); 201 memcpy(resp.io_buffer()->data(), response_data, sizeof(response_data));
133 memcpy(r1.io_buffer()->data(), &response_data[0],
134 r1.io_buffer()->size());
135 202
136 // Verify resolved IPs. 203 // reject too short
137 int response_size = arraysize(response_data); 204 EXPECT_FALSE(resp.InitParse(query->io_buffer()->size() - 1, *query));
138 IPAddressList actual_ips; 205
139 EXPECT_EQ(OK, r1.Parse(response_size, &actual_ips)); 206 // reject wrong id
140 EXPECT_EQ(expected_ips, actual_ips); 207 scoped_ptr<DnsQuery> other_query(query->CloneWithNewId(0xbeef));
208 EXPECT_FALSE(resp.InitParse(sizeof(response_data), *other_query));
209
210 // reject wrong question
211 scoped_ptr<DnsQuery> wrong_query(
212 new DnsQuery(0xcafe, qname, dns_protocol::kTypeCNAME));
213 EXPECT_FALSE(resp.InitParse(sizeof(response_data), *wrong_query));
214
215 // accept matching question
216 EXPECT_TRUE(resp.InitParse(sizeof(response_data), *query));
217
218 // check header access
219 EXPECT_EQ(0x81, resp.flags0());
220 EXPECT_EQ(0x80, resp.flags1());
221 EXPECT_EQ(0x0, resp.rcode());
222 EXPECT_EQ(2, resp.answer_count());
223
224 DnsResourceRecord record;
225 DnsRecordParser parser = resp.Parser();
226 EXPECT_TRUE(parser.ParseRecord(&record));
227 EXPECT_TRUE(parser.ParseRecord(&record));
228 EXPECT_FALSE(parser.ParseRecord(&record));
141 } 229 }
142 230
143 } // namespace net 231 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698