OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/time.h" | |
8 #include "net/base/address_list.h" | |
7 #include "net/base/io_buffer.h" | 9 #include "net/base/io_buffer.h" |
10 #include "net/base/net_util.h" | |
11 #include "net/base/sys_addrinfo.h" | |
8 #include "net/dns/dns_protocol.h" | 12 #include "net/dns/dns_protocol.h" |
9 #include "net/dns/dns_query.h" | 13 #include "net/dns/dns_query.h" |
14 #include "net/dns/dns_test_util.h" | |
10 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
11 | 16 |
12 namespace net { | 17 namespace net { |
13 | 18 |
14 namespace { | 19 namespace { |
15 | 20 |
16 TEST(DnsRecordParserTest, Constructor) { | 21 TEST(DnsRecordParserTest, Constructor) { |
17 const char data[] = { 0 }; | 22 const char data[] = { 0 }; |
18 | 23 |
19 EXPECT_FALSE(DnsRecordParser().IsValid()); | 24 EXPECT_FALSE(DnsRecordParser().IsValid()); |
20 EXPECT_TRUE(DnsRecordParser(data, 1, 0).IsValid()); | 25 EXPECT_TRUE(DnsRecordParser(data, 1, 0).IsValid()); |
21 EXPECT_TRUE(DnsRecordParser(data, 1, 1).IsValid()); | 26 EXPECT_TRUE(DnsRecordParser(data, 1, 1).IsValid()); |
22 | 27 |
23 EXPECT_FALSE(DnsRecordParser(data, 1, 0).AtEnd()); | 28 EXPECT_FALSE(DnsRecordParser(data, 1, 0).AtEnd()); |
24 EXPECT_TRUE(DnsRecordParser(data, 1, 1).AtEnd()); | 29 EXPECT_TRUE(DnsRecordParser(data, 1, 1).AtEnd()); |
25 } | 30 } |
26 | 31 |
27 TEST(DnsRecordParserTest, ParseName) { | 32 TEST(DnsRecordParserTest, ReadName) { |
28 const uint8 data[] = { | 33 const uint8 data[] = { |
29 // all labels "foo.example.com" | 34 // all labels "foo.example.com" |
30 0x03, 'f', 'o', 'o', | 35 0x03, 'f', 'o', 'o', |
31 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', | 36 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', |
32 0x03, 'c', 'o', 'm', | 37 0x03, 'c', 'o', 'm', |
33 // byte 0x10 | 38 // byte 0x10 |
34 0x00, | 39 0x00, |
35 // byte 0x11 | 40 // byte 0x11 |
36 // part label, part pointer, "bar.example.com" | 41 // part label, part pointer, "bar.example.com" |
37 0x03, 'b', 'a', 'r', | 42 0x03, 'b', 'a', 'r', |
38 0xc0, 0x04, | 43 0xc0, 0x04, |
39 // byte 0x17 | 44 // byte 0x17 |
40 // all pointer to "bar.example.com", 2 jumps | 45 // all pointer to "bar.example.com", 2 jumps |
41 0xc0, 0x11, | 46 0xc0, 0x11, |
42 // byte 0x1a | 47 // byte 0x1a |
43 }; | 48 }; |
44 | 49 |
45 std::string out; | 50 std::string out; |
46 DnsRecordParser parser(data, sizeof(data), 0); | 51 DnsRecordParser parser(data, sizeof(data), 0); |
47 ASSERT_TRUE(parser.IsValid()); | 52 ASSERT_TRUE(parser.IsValid()); |
48 | 53 |
49 EXPECT_EQ(0x11, parser.ParseName(data + 0x00, &out)); | 54 EXPECT_EQ(0x11, parser.ReadName(data + 0x00, &out)); |
50 EXPECT_EQ("foo.example.com", out); | 55 EXPECT_EQ("foo.example.com", out); |
51 // Check that the last "." is never stored. | 56 // Check that the last "." is never stored. |
52 out.clear(); | 57 out.clear(); |
53 EXPECT_EQ(0x1, parser.ParseName(data + 0x10, &out)); | 58 EXPECT_EQ(0x1, parser.ReadName(data + 0x10, &out)); |
54 EXPECT_EQ("", out); | 59 EXPECT_EQ("", out); |
55 out.clear(); | 60 out.clear(); |
56 EXPECT_EQ(0x6, parser.ParseName(data + 0x11, &out)); | 61 EXPECT_EQ(0x6, parser.ReadName(data + 0x11, &out)); |
57 EXPECT_EQ("bar.example.com", out); | 62 EXPECT_EQ("bar.example.com", out); |
58 out.clear(); | 63 out.clear(); |
59 EXPECT_EQ(0x2, parser.ParseName(data + 0x17, &out)); | 64 EXPECT_EQ(0x2, parser.ReadName(data + 0x17, &out)); |
60 EXPECT_EQ("bar.example.com", out); | 65 EXPECT_EQ("bar.example.com", out); |
61 | 66 |
62 // Parse name without storing it. | 67 // Parse name without storing it. |
63 EXPECT_EQ(0x11, parser.ParseName(data + 0x00, NULL)); | 68 EXPECT_EQ(0x11, parser.ReadName(data + 0x00, NULL)); |
64 EXPECT_EQ(0x1, parser.ParseName(data + 0x10, NULL)); | 69 EXPECT_EQ(0x1, parser.ReadName(data + 0x10, NULL)); |
65 EXPECT_EQ(0x6, parser.ParseName(data + 0x11, NULL)); | 70 EXPECT_EQ(0x6, parser.ReadName(data + 0x11, NULL)); |
66 EXPECT_EQ(0x2, parser.ParseName(data + 0x17, NULL)); | 71 EXPECT_EQ(0x2, parser.ReadName(data + 0x17, NULL)); |
67 | 72 |
68 // Check that it works even if initial position is different. | 73 // Check that it works even if initial position is different. |
69 parser = DnsRecordParser(data, sizeof(data), 0x12); | 74 parser = DnsRecordParser(data, sizeof(data), 0x12); |
70 EXPECT_EQ(0x6, parser.ParseName(data + 0x11, NULL)); | 75 EXPECT_EQ(0x6, parser.ReadName(data + 0x11, NULL)); |
71 } | 76 } |
72 | 77 |
73 TEST(DnsRecordParserTest, ParseNameFail) { | 78 TEST(DnsRecordParserTest, ReadNameFail) { |
74 const uint8 data[] = { | 79 const uint8 data[] = { |
75 // label length beyond packet | 80 // label length beyond packet |
76 0x30, 'x', 'x', | 81 0x30, 'x', 'x', |
77 0x00, | 82 0x00, |
78 // pointer offset beyond packet | 83 // pointer offset beyond packet |
79 0xc0, 0x20, | 84 0xc0, 0x20, |
80 // pointer loop | 85 // pointer loop |
81 0xc0, 0x08, | 86 0xc0, 0x08, |
82 0xc0, 0x06, | 87 0xc0, 0x06, |
83 // incorrect label type (currently supports only direct and pointer) | 88 // incorrect label type (currently supports only direct and pointer) |
84 0x80, 0x00, | 89 0x80, 0x00, |
85 // truncated name (missing root label) | 90 // truncated name (missing root label) |
86 0x02, 'x', 'x', | 91 0x02, 'x', 'x', |
87 }; | 92 }; |
88 | 93 |
89 DnsRecordParser parser(data, sizeof(data), 0); | 94 DnsRecordParser parser(data, sizeof(data), 0); |
90 ASSERT_TRUE(parser.IsValid()); | 95 ASSERT_TRUE(parser.IsValid()); |
91 | 96 |
92 std::string out; | 97 std::string out; |
93 EXPECT_EQ(0, parser.ParseName(data + 0x00, &out)); | 98 EXPECT_EQ(0, parser.ReadName(data + 0x00, &out)); |
94 EXPECT_EQ(0, parser.ParseName(data + 0x04, &out)); | 99 EXPECT_EQ(0, parser.ReadName(data + 0x04, &out)); |
95 EXPECT_EQ(0, parser.ParseName(data + 0x08, &out)); | 100 EXPECT_EQ(0, parser.ReadName(data + 0x08, &out)); |
96 EXPECT_EQ(0, parser.ParseName(data + 0x0a, &out)); | 101 EXPECT_EQ(0, parser.ReadName(data + 0x0a, &out)); |
97 EXPECT_EQ(0, parser.ParseName(data + 0x0c, &out)); | 102 EXPECT_EQ(0, parser.ReadName(data + 0x0c, &out)); |
98 EXPECT_EQ(0, parser.ParseName(data + 0x0e, &out)); | 103 EXPECT_EQ(0, parser.ReadName(data + 0x0e, &out)); |
99 } | 104 } |
100 | 105 |
101 TEST(DnsRecordParserTest, ParseRecord) { | 106 TEST(DnsRecordParserTest, ReadRecord) { |
102 const uint8 data[] = { | 107 const uint8 data[] = { |
103 // Type CNAME record. | 108 // Type CNAME record. |
104 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', | 109 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', |
105 0x03, 'c', 'o', 'm', | 110 0x03, 'c', 'o', 'm', |
106 0x00, | 111 0x00, |
107 0x00, 0x05, // TYPE is CNAME. | 112 0x00, 0x05, // TYPE is CNAME. |
108 0x00, 0x01, // CLASS is IN. | 113 0x00, 0x01, // CLASS is IN. |
109 0x00, 0x01, 0x24, 0x74, // TTL is 0x00012474. | 114 0x00, 0x01, 0x24, 0x74, // TTL is 0x00012474. |
110 0x00, 0x06, // RDLENGTH is 6 bytes. | 115 0x00, 0x06, // RDLENGTH is 6 bytes. |
111 0x03, 'f', 'o', 'o', // compressed name in record | 116 0x03, 'f', 'o', 'o', // compressed name in record |
112 0xc0, 0x00, | 117 0xc0, 0x00, |
113 // Type A record. | 118 // Type A record. |
114 0x03, 'b', 'a', 'r', // compressed owner name | 119 0x03, 'b', 'a', 'r', // compressed owner name |
115 0xc0, 0x00, | 120 0xc0, 0x00, |
116 0x00, 0x01, // TYPE is A. | 121 0x00, 0x01, // TYPE is A. |
117 0x00, 0x01, // CLASS is IN. | 122 0x00, 0x01, // CLASS is IN. |
118 0x00, 0x20, 0x13, 0x55, // TTL is 0x00201355. | 123 0x00, 0x20, 0x13, 0x55, // TTL is 0x00201355. |
119 0x00, 0x04, // RDLENGTH is 4 bytes. | 124 0x00, 0x04, // RDLENGTH is 4 bytes. |
120 0x7f, 0x02, 0x04, 0x01, // IP is 127.2.4.1 | 125 0x7f, 0x02, 0x04, 0x01, // IP is 127.2.4.1 |
121 }; | 126 }; |
122 | 127 |
123 std::string out; | 128 std::string out; |
124 DnsRecordParser parser(data, sizeof(data), 0); | 129 DnsRecordParser parser(data, sizeof(data), 0); |
125 | 130 |
126 DnsResourceRecord record; | 131 DnsResourceRecord record; |
127 EXPECT_TRUE(parser.ParseRecord(&record)); | 132 EXPECT_TRUE(parser.ReadRecord(&record)); |
128 EXPECT_EQ("example.com", record.name); | 133 EXPECT_EQ("example.com", record.name); |
129 EXPECT_EQ(dns_protocol::kTypeCNAME, record.type); | 134 EXPECT_EQ(dns_protocol::kTypeCNAME, record.type); |
130 EXPECT_EQ(dns_protocol::kClassIN, record.klass); | 135 EXPECT_EQ(dns_protocol::kClassIN, record.klass); |
131 EXPECT_EQ(0x00012474u, record.ttl); | 136 EXPECT_EQ(0x00012474u, record.ttl); |
132 EXPECT_EQ(6u, record.rdata.length()); | 137 EXPECT_EQ(6u, record.rdata.length()); |
133 EXPECT_EQ(6, parser.ParseName(record.rdata.data(), &out)); | 138 EXPECT_EQ(6, parser.ReadName(record.rdata.data(), &out)); |
134 EXPECT_EQ("foo.example.com", out); | 139 EXPECT_EQ("foo.example.com", out); |
135 EXPECT_FALSE(parser.AtEnd()); | 140 EXPECT_FALSE(parser.AtEnd()); |
136 | 141 |
137 EXPECT_TRUE(parser.ParseRecord(&record)); | 142 EXPECT_TRUE(parser.ReadRecord(&record)); |
138 EXPECT_EQ("bar.example.com", record.name); | 143 EXPECT_EQ("bar.example.com", record.name); |
139 EXPECT_EQ(dns_protocol::kTypeA, record.type); | 144 EXPECT_EQ(dns_protocol::kTypeA, record.type); |
140 EXPECT_EQ(dns_protocol::kClassIN, record.klass); | 145 EXPECT_EQ(dns_protocol::kClassIN, record.klass); |
141 EXPECT_EQ(0x00201355u, record.ttl); | 146 EXPECT_EQ(0x00201355u, record.ttl); |
142 EXPECT_EQ(4u, record.rdata.length()); | 147 EXPECT_EQ(4u, record.rdata.length()); |
143 EXPECT_EQ(base::StringPiece("\x7f\x02\x04\x01"), record.rdata); | 148 EXPECT_EQ(base::StringPiece("\x7f\x02\x04\x01"), record.rdata); |
144 EXPECT_TRUE(parser.AtEnd()); | 149 EXPECT_TRUE(parser.AtEnd()); |
145 | 150 |
146 // Test truncated record. | 151 // Test truncated record. |
147 parser = DnsRecordParser(data, sizeof(data) - 2, 0); | 152 parser = DnsRecordParser(data, sizeof(data) - 2, 0); |
148 EXPECT_TRUE(parser.ParseRecord(&record)); | 153 EXPECT_TRUE(parser.ReadRecord(&record)); |
149 EXPECT_FALSE(parser.AtEnd()); | 154 EXPECT_FALSE(parser.AtEnd()); |
150 EXPECT_FALSE(parser.ParseRecord(&record)); | 155 EXPECT_FALSE(parser.ReadRecord(&record)); |
151 } | 156 } |
152 | 157 |
153 TEST(DnsResponseTest, InitParse) { | 158 TEST(DnsResponseTest, InitParse) { |
154 // This includes \0 at the end. | 159 // This includes \0 at the end. |
155 const char qname_data[] = "\x0A""codereview""\x08""chromium""\x03""org"; | 160 const char qname_data[] = "\x0A""codereview""\x08""chromium""\x03""org"; |
156 const base::StringPiece qname(qname_data, sizeof(qname_data)); | 161 const base::StringPiece qname(qname_data, sizeof(qname_data)); |
157 // Compilers want to copy when binding temporary to const &, so must use heap. | 162 // 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)); | 163 scoped_ptr<DnsQuery> query(new DnsQuery(0xcafe, qname, dns_protocol::kTypeA)); |
159 | 164 |
160 const uint8 response_data[] = { | 165 const uint8 response_data[] = { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 EXPECT_EQ(0x0, resp.rcode()); | 232 EXPECT_EQ(0x0, resp.rcode()); |
228 EXPECT_EQ(2, resp.answer_count()); | 233 EXPECT_EQ(2, resp.answer_count()); |
229 | 234 |
230 // Check question access. | 235 // Check question access. |
231 EXPECT_EQ(query->qname(), resp.qname()); | 236 EXPECT_EQ(query->qname(), resp.qname()); |
232 EXPECT_EQ(query->qtype(), resp.qtype()); | 237 EXPECT_EQ(query->qtype(), resp.qtype()); |
233 EXPECT_EQ("codereview.chromium.org", resp.GetDottedName()); | 238 EXPECT_EQ("codereview.chromium.org", resp.GetDottedName()); |
234 | 239 |
235 DnsResourceRecord record; | 240 DnsResourceRecord record; |
236 DnsRecordParser parser = resp.Parser(); | 241 DnsRecordParser parser = resp.Parser(); |
237 EXPECT_TRUE(parser.ParseRecord(&record)); | 242 EXPECT_TRUE(parser.ReadRecord(&record)); |
238 EXPECT_FALSE(parser.AtEnd()); | 243 EXPECT_FALSE(parser.AtEnd()); |
239 EXPECT_TRUE(parser.ParseRecord(&record)); | 244 EXPECT_TRUE(parser.ReadRecord(&record)); |
240 EXPECT_TRUE(parser.AtEnd()); | 245 EXPECT_TRUE(parser.AtEnd()); |
241 EXPECT_FALSE(parser.ParseRecord(&record)); | 246 EXPECT_FALSE(parser.ReadRecord(&record)); |
247 } | |
248 | |
249 void VerifyAddressList(const std::vector<const char*>& ip_addresses, | |
250 const AddressList& addrlist) { | |
251 ASSERT_GT(ip_addresses.size(), 0u); | |
252 ASSERT_NE(static_cast<addrinfo*>(NULL), addrlist.head()); | |
253 | |
254 IPAddressNumber ip_number; | |
255 const struct addrinfo* ainfo = addrlist.head(); | |
256 for (std::vector<const char*>::const_iterator i = ip_addresses.begin(); | |
257 i != ip_addresses.end(); ++i, ainfo = ainfo->ai_next) { | |
258 ASSERT_NE(static_cast<addrinfo*>(NULL), ainfo); | |
259 EXPECT_EQ(sizeof(struct sockaddr_in), | |
260 static_cast<size_t>(ainfo->ai_addrlen)); | |
261 | |
262 const struct sockaddr* sa = ainfo->ai_addr; | |
263 EXPECT_STREQ(*i, NetAddressToString(sa, ainfo->ai_addrlen).c_str()); | |
264 } | |
265 ASSERT_EQ(static_cast<addrinfo*>(NULL), ainfo); | |
266 } | |
267 | |
268 TEST(DnsResponseTest, ParseToAddressList) { | |
269 const struct TestCase { | |
270 const uint8* query_data; | |
271 size_t query_size; | |
272 const uint8* response_data; | |
273 size_t response_size; | |
274 const char* const* expected_addresses; | |
275 size_t num_expected_addresses; | |
276 const char* expected_cname; | |
277 int expected_ttl_sec; | |
278 } cases[] = { | |
279 { | |
280 kT0QueryDatagram, arraysize(kT0QueryDatagram), | |
281 kT0ResponseDatagram, arraysize(kT0ResponseDatagram), | |
282 kT0IpAddresses, arraysize(kT0IpAddresses), | |
283 kT0CanonName, | |
284 kT0TTL, | |
285 }, | |
286 { | |
287 kT1QueryDatagram, arraysize(kT1QueryDatagram), | |
288 kT1ResponseDatagram, arraysize(kT1ResponseDatagram), | |
289 kT1IpAddresses, arraysize(kT1IpAddresses), | |
290 kT1CanonName, | |
291 kT1TTL, | |
292 }, | |
293 { | |
294 kT2QueryDatagram, arraysize(kT2QueryDatagram), | |
295 kT2ResponseDatagram, arraysize(kT2ResponseDatagram), | |
296 kT2IpAddresses, arraysize(kT2IpAddresses), | |
297 kT2CanonName, | |
298 kT2TTL, | |
299 }, | |
300 { | |
301 kT3QueryDatagram, arraysize(kT3QueryDatagram), | |
302 kT3ResponseDatagram, arraysize(kT3ResponseDatagram), | |
303 kT3IpAddresses, arraysize(kT3IpAddresses), | |
304 kT3CanonName, | |
305 kT3TTL, | |
306 }, | |
307 }; | |
308 | |
309 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
cbentzel
2012/02/15 19:48:35
You should add tests for each of the unsuccessful
| |
310 const TestCase& t = cases[i]; | |
311 DnsResponse response(t.response_data, t.response_size, t.query_size); | |
312 AddressList addr_list; | |
313 base::TimeDelta ttl; | |
314 EXPECT_EQ(DnsResponse::DNS_SUCCESS, | |
315 response.ParseToAddressList(&addr_list, &ttl)); | |
316 std::vector<const char*> expected_addresses( | |
317 t.expected_addresses, | |
318 t.expected_addresses + t.num_expected_addresses); | |
319 VerifyAddressList(expected_addresses, addr_list); | |
320 std::string cname; | |
321 ASSERT_TRUE(addr_list.GetCanonicalName(&cname)); | |
322 EXPECT_EQ(t.expected_cname, cname); | |
323 EXPECT_EQ(base::TimeDelta::FromSeconds(t.expected_ttl_sec), ttl); | |
324 } | |
242 } | 325 } |
243 | 326 |
244 } // namespace | 327 } // namespace |
245 | 328 |
246 } // namespace net | 329 } // namespace net |
OLD | NEW |