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

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