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

Side by Side Diff: components/certificate_transparency/mock_log_dns_traffic.cc

Issue 2348393002: Minor improvements to MockLogDnsTraffic (Closed)
Patch Set: Forward declare MockSocketData Created 4 years, 2 months 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "components/certificate_transparency/mock_log_dns_traffic.h" 5 #include "components/certificate_transparency/mock_log_dns_traffic.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <numeric> 8 #include <numeric>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/big_endian.h" 11 #include "base/big_endian.h"
12 #include "base/sys_byteorder.h" 12 #include "base/sys_byteorder.h"
13 #include "base/test/test_timeouts.h" 13 #include "base/test/test_timeouts.h"
14 #include "net/dns/dns_client.h" 14 #include "net/dns/dns_client.h"
15 #include "net/dns/dns_protocol.h" 15 #include "net/dns/dns_protocol.h"
16 #include "net/dns/dns_util.h" 16 #include "net/dns/dns_util.h"
17 #include "net/socket/socket_test_util.h" 17 #include "net/socket/socket_test_util.h"
18 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
19 19
20 namespace certificate_transparency { 20 namespace certificate_transparency {
21 21
22 namespace { 22 namespace {
23 23
24 // Prevents read overruns and makes a socket timeout the default behaviour.
Ryan Sleevi 2016/10/03 23:44:52 How? That's perhaps the subtle part of this code,
Rob Percival 2016/10/05 15:42:00 It's consistent with the other code I saw using mo
25 const net::MockRead kNoMoreData(net::SYNCHRONOUS, net::ERR_IO_PENDING, 2);
26
24 // Necessary to expose SetDnsConfig for testing. 27 // Necessary to expose SetDnsConfig for testing.
25 class DnsChangeNotifier : public net::NetworkChangeNotifier { 28 class DnsChangeNotifier : public net::NetworkChangeNotifier {
26 public: 29 public:
27 static void SetInitialDnsConfig(const net::DnsConfig& config) { 30 static void SetInitialDnsConfig(const net::DnsConfig& config) {
28 net::NetworkChangeNotifier::SetInitialDnsConfig(config); 31 net::NetworkChangeNotifier::SetInitialDnsConfig(config);
29 } 32 }
30 33
31 static void SetDnsConfig(const net::DnsConfig& config) { 34 static void SetDnsConfig(const net::DnsConfig& config) {
32 net::NetworkChangeNotifier::SetDnsConfig(config); 35 net::NetworkChangeNotifier::SetDnsConfig(config);
33 } 36 }
34 }; 37 };
35 38
36 // Always return min, to simplify testing. 39 // Always return min, to simplify testing.
37 // This should result in the DNS query ID always being 0. 40 // This should result in the DNS query ID always being 0.
38 int FakeRandInt(int min, int max) { 41 int FakeRandInt(int min, int max) {
39 return min; 42 return min;
40 } 43 }
41 44
42 std::vector<char> CreateDnsTxtRequest(base::StringPiece qname) { 45 std::vector<char> CreateDnsTxtRequest(base::StringPiece qname) {
43 std::string encoded_qname; 46 std::string encoded_qname;
44 EXPECT_TRUE(net::DNSDomainFromDot(qname, &encoded_qname)); 47 DCHECK(net::DNSDomainFromDot(qname, &encoded_qname));
Ryan Sleevi 2016/10/03 23:44:52 Don't DCHECK in tests. Throughout.
Rob Percival 2016/10/05 15:42:00 Please see https://chromiumcodereview-hr.appspot.c
45 48
46 // DNS query section: 49 // DNS query section:
47 // N bytes - qname 50 // N bytes - qname
48 // 2 bytes - record type 51 // 2 bytes - record type
49 // 2 bytes - record class 52 // 2 bytes - record class
50 // Total = N + 4 bytes 53 // Total = N + 4 bytes
51 const size_t query_section_size = encoded_qname.size() + 4; 54 const size_t query_section_size = encoded_qname.size() + 4;
52 55
53 std::vector<char> request(sizeof(net::dns_protocol::Header) + 56 std::vector<char> request(sizeof(net::dns_protocol::Header) +
54 query_section_size); 57 query_section_size);
55 base::BigEndianWriter writer(request.data(), request.size()); 58 base::BigEndianWriter writer(request.data(), request.size());
56 59
57 // Header 60 // Header
58 net::dns_protocol::Header header = {}; 61 net::dns_protocol::Header header = {};
59 header.flags = base::HostToNet16(net::dns_protocol::kFlagRD); 62 header.flags = base::HostToNet16(net::dns_protocol::kFlagRD);
60 header.qdcount = base::HostToNet16(1); 63 header.qdcount = base::HostToNet16(1);
61 EXPECT_TRUE(writer.WriteBytes(&header, sizeof(header))); 64 DCHECK(writer.WriteBytes(&header, sizeof(header)));
62 // Query section 65 // Query section
63 EXPECT_TRUE(writer.WriteBytes(encoded_qname.data(), encoded_qname.size())); 66 DCHECK(writer.WriteBytes(encoded_qname.data(), encoded_qname.size()));
64 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kTypeTXT)); 67 DCHECK(writer.WriteU16(net::dns_protocol::kTypeTXT));
65 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kClassIN)); 68 DCHECK(writer.WriteU16(net::dns_protocol::kClassIN));
66 EXPECT_EQ(0, writer.remaining()); 69 DCHECK_EQ(0, writer.remaining());
67 70
68 return request; 71 return request;
69 } 72 }
70 73
71 std::vector<char> CreateDnsTxtResponse(const std::vector<char>& request, 74 std::vector<char> CreateDnsTxtResponse(const std::vector<char>& request,
72 base::StringPiece answer) { 75 base::StringPiece answer) {
73 // DNS answers section: 76 // DNS answers section:
74 // 2 bytes - qname pointer 77 // 2 bytes - qname pointer
75 // 2 bytes - record type 78 // 2 bytes - record type
76 // 2 bytes - record class 79 // 2 bytes - record class
77 // 4 bytes - time-to-live 80 // 4 bytes - time-to-live
78 // 2 bytes - size of answer (N) 81 // 2 bytes - size of answer (N)
79 // N bytes - answer 82 // N bytes - answer
80 // Total = 12 + N bytes 83 // Total = 12 + N bytes
81 const size_t answers_section_size = 12 + answer.size(); 84 const size_t answers_section_size = 12 + answer.size();
82 constexpr uint32_t ttl = 86400; // seconds 85 constexpr uint32_t ttl = 86400; // seconds
83 86
84 std::vector<char> response(request.size() + answers_section_size); 87 std::vector<char> response(request.size() + answers_section_size);
85 std::copy(request.begin(), request.end(), response.begin()); 88 std::copy(request.begin(), request.end(), response.begin());
86 // Modify the header 89 // Modify the header
87 net::dns_protocol::Header* header = 90 net::dns_protocol::Header* header =
88 reinterpret_cast<net::dns_protocol::Header*>(response.data()); 91 reinterpret_cast<net::dns_protocol::Header*>(response.data());
89 header->ancount = base::HostToNet16(1); 92 header->ancount = base::HostToNet16(1);
90 header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse); 93 header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse);
91 94
92 // Write the answer section 95 // Write the answer section
93 base::BigEndianWriter writer(response.data() + request.size(), 96 base::BigEndianWriter writer(response.data() + request.size(),
94 response.size() - request.size()); 97 response.size() - request.size());
95 EXPECT_TRUE(writer.WriteU8(0xc0)); // qname is a pointer 98 DCHECK(writer.WriteU8(0xc0)); // qname is a pointer
96 EXPECT_TRUE(writer.WriteU8( 99 DCHECK(writer.WriteU8(
97 sizeof(*header))); // address of qname (start of query section) 100 sizeof(*header))); // address of qname (start of query section)
98 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kTypeTXT)); 101 DCHECK(writer.WriteU16(net::dns_protocol::kTypeTXT));
99 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kClassIN)); 102 DCHECK(writer.WriteU16(net::dns_protocol::kClassIN));
100 EXPECT_TRUE(writer.WriteU32(ttl)); 103 DCHECK(writer.WriteU32(ttl));
101 EXPECT_TRUE(writer.WriteU16(answer.size())); 104 DCHECK(writer.WriteU16(answer.size()));
102 EXPECT_TRUE(writer.WriteBytes(answer.data(), answer.size())); 105 DCHECK(writer.WriteBytes(answer.data(), answer.size()));
103 EXPECT_EQ(0, writer.remaining()); 106 DCHECK_EQ(0, writer.remaining());
104 107
105 return response; 108 return response;
106 } 109 }
107 110
108 std::vector<char> CreateDnsErrorResponse(const std::vector<char>& request, 111 std::vector<char> CreateDnsErrorResponse(const std::vector<char>& request,
109 uint8_t rcode) { 112 uint8_t rcode) {
110 std::vector<char> response(request); 113 std::vector<char> response(request);
111 // Modify the header 114 // Modify the header
112 net::dns_protocol::Header* header = 115 net::dns_protocol::Header* header =
113 reinterpret_cast<net::dns_protocol::Header*>(response.data()); 116 reinterpret_cast<net::dns_protocol::Header*>(response.data());
114 header->ancount = base::HostToNet16(1); 117 header->ancount = base::HostToNet16(1);
115 header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse | rcode); 118 header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse | rcode);
116 119
117 return response; 120 return response;
118 } 121 }
119 122
120 } // namespace 123 } // namespace
121 124
122 namespace internal { 125 // A container for all of the data needed for simulating a socket.
126 // This is useful because Mock{Read,Write}, SequencedSocketData and
127 // MockClientSocketFactory all do not take ownership of or copy their arguments,
128 // so it is necessary to manage the lifetime of those arguments. Wrapping all
129 // of that up in a single class simplifies this.
130 class MockLogDnsTraffic::MockSocketData {
131 public:
132 // A socket that expects one write and one read operation.
133 MockSocketData(const std::vector<char>& write, const std::vector<char>& read)
134 : expected_write_payload_(write),
135 expected_read_payload_(read),
136 expected_write_(net::SYNCHRONOUS,
137 expected_write_payload_.data(),
138 expected_write_payload_.size(),
139 0),
140 expected_reads_{net::MockRead(net::ASYNC,
141 expected_read_payload_.data(),
142 expected_read_payload_.size(),
143 1),
144 kNoMoreData},
145 socket_data_(expected_reads_, 2, &expected_write_, 1) {}
123 146
124 MockSocketData::MockSocketData(const std::vector<char>& write, 147 // A socket that expects one write and a read error.
125 const std::vector<char>& read) 148 MockSocketData(const std::vector<char>& write, net::Error error)
126 : expected_write_payload_(write), 149 : expected_write_payload_(write),
127 expected_read_payload_(read), 150 expected_write_(net::SYNCHRONOUS,
128 expected_write_(net::SYNCHRONOUS, 151 expected_write_payload_.data(),
129 expected_write_payload_.data(), 152 expected_write_payload_.size(),
130 expected_write_payload_.size(), 153 0),
131 0), 154 expected_reads_{net::MockRead(net::ASYNC, error, 1), kNoMoreData},
132 expected_reads_{net::MockRead(net::ASYNC, 155 socket_data_(expected_reads_, 2, &expected_write_, 1) {}
133 expected_read_payload_.data(),
134 expected_read_payload_.size(),
135 1),
136 no_more_data_},
137 socket_data_(expected_reads_, 2, &expected_write_, 1) {}
138 156
139 MockSocketData::MockSocketData(const std::vector<char>& write, int net_error) 157 // A socket that expects one write and no response.
140 : expected_write_payload_(write), 158 explicit MockSocketData(const std::vector<char>& write)
141 expected_write_(net::SYNCHRONOUS, 159 : expected_write_payload_(write),
142 expected_write_payload_.data(), 160 expected_write_(net::SYNCHRONOUS,
143 expected_write_payload_.size(), 161 expected_write_payload_.data(),
144 0), 162 expected_write_payload_.size(),
145 expected_reads_{net::MockRead(net::ASYNC, net_error, 1), no_more_data_}, 163 0),
146 socket_data_(expected_reads_, 2, &expected_write_, 1) {} 164 expected_reads_{net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING, 1),
165 kNoMoreData},
166 socket_data_(expected_reads_, 2, &expected_write_, 1) {}
147 167
148 MockSocketData::MockSocketData(const std::vector<char>& write) 168 ~MockSocketData() {}
149 : expected_write_payload_(write),
150 expected_write_(net::SYNCHRONOUS,
151 expected_write_payload_.data(),
152 expected_write_payload_.size(),
153 0),
154 expected_reads_{net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING, 1),
155 no_more_data_},
156 socket_data_(expected_reads_, 2, &expected_write_, 1) {}
157 169
158 MockSocketData::~MockSocketData() {} 170 void SetWriteMode(net::IoMode mode) { expected_write_.mode = mode; }
171 void SetReadMode(net::IoMode mode) { expected_reads_[0].mode = mode; }
159 172
160 void MockSocketData::AddToFactory( 173 void AddToFactory(net::MockClientSocketFactory* socket_factory) {
161 net::MockClientSocketFactory* socket_factory) { 174 socket_factory->AddSocketDataProvider(&socket_data_);
162 socket_factory->AddSocketDataProvider(&socket_data_); 175 }
163 }
164 176
165 const net::MockRead MockSocketData::no_more_data_(net::SYNCHRONOUS, 177 private:
166 net::ERR_IO_PENDING, 178 // This class only supports one write and one read, so just need to store one
167 2); 179 // payload each.
180 const std::vector<char> expected_write_payload_;
181 const std::vector<char> expected_read_payload_;
168 182
169 } // namespace internal 183 // Encapsulates the data that is expected to be written to a socket.
184 net::MockWrite expected_write_;
170 185
171 using internal::MockSocketData; 186 // Encapsulates the data/error that should be returned when reading from a
187 // socket. The second "expected" read is a sentinel that causes socket reads
188 // beyond the first to hang until they timeout. This results in better
189 // test failure messages (rather than a CHECK-fail due to a socket read
190 // overrunning the MockRead array) and behaviour more like a real socket when
191 // an unexpected second socket read occurs.
192 net::MockRead expected_reads_[2];
193
194 // Holds pointers to |expected_write_| and |expected_reads_|. This is what is
195 // added to net::MockClientSocketFactory to prepare a mock socket.
196 net::SequencedSocketData socket_data_;
197
198 DISALLOW_COPY_AND_ASSIGN(MockSocketData);
199 };
172 200
173 MockLogDnsTraffic::MockLogDnsTraffic() : socket_read_mode_(net::ASYNC) {} 201 MockLogDnsTraffic::MockLogDnsTraffic() : socket_read_mode_(net::ASYNC) {}
174 202
175 MockLogDnsTraffic::~MockLogDnsTraffic() {} 203 MockLogDnsTraffic::~MockLogDnsTraffic() {}
176 204
177 void MockLogDnsTraffic::ExpectRequestAndErrorResponse(base::StringPiece qname, 205 void MockLogDnsTraffic::ExpectRequestAndErrorResponse(base::StringPiece qname,
178 uint8_t rcode) { 206 uint8_t rcode) {
179 std::vector<char> request = CreateDnsTxtRequest(qname); 207 std::vector<char> request = CreateDnsTxtRequest(qname);
180 EmplaceMockSocketData(CreateDnsTxtRequest(qname), 208 EmplaceMockSocketData(CreateDnsTxtRequest(qname),
181 CreateDnsErrorResponse(request, rcode)); 209 CreateDnsErrorResponse(request, rcode));
182 } 210 }
183 211
184 void MockLogDnsTraffic::ExpectRequestAndSocketError(base::StringPiece qname, 212 void MockLogDnsTraffic::ExpectRequestAndSocketError(base::StringPiece qname,
185 int net_error) { 213 net::Error error) {
186 EmplaceMockSocketData(CreateDnsTxtRequest(qname), net_error); 214 EmplaceMockSocketData(CreateDnsTxtRequest(qname), error);
187 } 215 }
188 216
189 void MockLogDnsTraffic::ExpectRequestAndTimeout(base::StringPiece qname) { 217 void MockLogDnsTraffic::ExpectRequestAndTimeout(base::StringPiece qname) {
190 EmplaceMockSocketData(CreateDnsTxtRequest(qname)); 218 EmplaceMockSocketData(CreateDnsTxtRequest(qname));
191 219
192 // Speed up timeout tests. 220 // Speed up timeout tests.
193 SetDnsTimeout(TestTimeouts::tiny_timeout()); 221 SetDnsTimeout(TestTimeouts::tiny_timeout());
194 } 222 }
195 223
196 void MockLogDnsTraffic::ExpectLeafIndexRequestAndResponse( 224 void MockLogDnsTraffic::ExpectLeafIndexRequestAndResponse(
197 base::StringPiece qname, 225 base::StringPiece qname,
198 base::StringPiece leaf_index) { 226 base::StringPiece leaf_index) {
199 // Prepend size to leaf_index to create the query answer (rdata) 227 // Prepend size to leaf_index to create the query answer (rdata)
200 ASSERT_LE(leaf_index.size(), 0xFFul); // size must fit into a single byte 228 DCHECK_LE(leaf_index.size(), 0xFFul); // size must fit into a single byte
201 std::string answer = leaf_index.as_string(); 229 std::string answer = leaf_index.as_string();
202 answer.insert(answer.begin(), static_cast<char>(leaf_index.size())); 230 answer.insert(answer.begin(), static_cast<char>(leaf_index.size()));
203 231
204 ExpectRequestAndResponse(qname, answer); 232 ExpectRequestAndResponse(qname, answer);
205 } 233 }
206 234
207 void MockLogDnsTraffic::ExpectAuditProofRequestAndResponse( 235 void MockLogDnsTraffic::ExpectAuditProofRequestAndResponse(
208 base::StringPiece qname, 236 base::StringPiece qname,
209 std::vector<std::string>::const_iterator audit_path_start, 237 std::vector<std::string>::const_iterator audit_path_start,
210 std::vector<std::string>::const_iterator audit_path_end) { 238 std::vector<std::string>::const_iterator audit_path_end) {
211 // Join nodes in the audit path into a single string. 239 // Join nodes in the audit path into a single string.
212 std::string proof = 240 std::string proof =
213 std::accumulate(audit_path_start, audit_path_end, std::string()); 241 std::accumulate(audit_path_start, audit_path_end, std::string());
214 242
215 // Prepend size to proof to create the query answer (rdata) 243 // Prepend size to proof to create the query answer (rdata)
216 ASSERT_LE(proof.size(), 0xFFul); // size must fit into a single byte 244 DCHECK_LE(proof.size(), 0xFFul); // size must fit into a single byte
217 proof.insert(proof.begin(), static_cast<char>(proof.size())); 245 proof.insert(proof.begin(), static_cast<char>(proof.size()));
218 246
219 ExpectRequestAndResponse(qname, proof); 247 ExpectRequestAndResponse(qname, proof);
220 } 248 }
221 249
222 void MockLogDnsTraffic::InitializeDnsConfig() { 250 void MockLogDnsTraffic::InitializeDnsConfig() {
223 net::DnsConfig dns_config; 251 net::DnsConfig dns_config;
224 // Use an invalid nameserver address. This prevents the tests accidentally 252 // Use an invalid nameserver address. This prevents the tests accidentally
225 // sending real DNS queries. The mock sockets don't care that the address 253 // sending real DNS queries. The mock sockets don't care that the address
226 // is invalid. 254 // is invalid.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 } 289 }
262 290
263 void MockLogDnsTraffic::SetDnsTimeout(const base::TimeDelta& timeout) { 291 void MockLogDnsTraffic::SetDnsTimeout(const base::TimeDelta& timeout) {
264 net::DnsConfig dns_config; 292 net::DnsConfig dns_config;
265 DnsChangeNotifier::GetDnsConfig(&dns_config); 293 DnsChangeNotifier::GetDnsConfig(&dns_config);
266 dns_config.timeout = timeout; 294 dns_config.timeout = timeout;
267 DnsChangeNotifier::SetDnsConfig(dns_config); 295 DnsChangeNotifier::SetDnsConfig(dns_config);
268 } 296 }
269 297
270 } // namespace certificate_transparency 298 } // namespace certificate_transparency
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698