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

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

Powered by Google App Engine
This is Rietveld 408576698