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

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

Issue 2066553002: Certificate Transparency DNS log client (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mock_dns_responses
Patch Set: Rebase Created 4 years, 6 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
« no previous file with comments | « components/certificate_transparency/log_dns_client.cc ('k') | components/components_tests.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/certificate_transparency/log_dns_client.h"
6
7 #include <algorithm>
8 #include <numeric>
9 #include <utility>
10 #include <vector>
11
12 #include "base/big_endian.h"
13 #include "base/macros.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/run_loop.h"
16 #include "base/sys_byteorder.h"
17 #include "base/test/simple_test_clock.h"
18 #include "base/test/test_timeouts.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "crypto/sha2.h"
21 #include "net/base/net_errors.h"
22 #include "net/cert/merkle_audit_proof.h"
23 #include "net/cert/merkle_tree_leaf.h"
24 #include "net/cert/signed_certificate_timestamp.h"
25 #include "net/dns/dns_client.h"
26 #include "net/dns/dns_config_service.h"
27 #include "net/dns/dns_protocol.h"
28 #include "net/log/test_net_log.h"
29 #include "net/socket/socket_test_util.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 namespace certificate_transparency {
34 namespace {
35
36 using ::testing::AllOf;
37 using ::testing::DeleteArg;
38 using ::testing::IsNull;
39 using ::testing::Not;
40 using ::testing::Pointee;
41 using ::testing::Field;
42 using ::testing::SizeIs;
43
44 constexpr char kLeafHash[] =
45 "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8"
46 "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04";
47
48 MATCHER(IsNetOk, "") {
49 if (arg <= net::OK)
50 *result_listener << net::ErrorToString(arg);
51 return arg == net::OK;
52 }
53
54 MATCHER_P(IsNetError, expected, "") {
55 if (arg <= net::OK)
56 *result_listener << net::ErrorToString(arg);
57 return arg == expected;
58 }
59
60 // Always return min, to simplify testing.
61 // This should result in the DNS query ID always being 0.
62 int FakeRandInt(int min, int max) {
63 return min;
64 }
65
66 std::vector<char> CreateDnsTxtRequest(base::StringPiece qname) {
67 std::string encoded_qname;
68 EXPECT_TRUE(net::DNSDomainFromDot(qname, &encoded_qname));
69
70 const size_t query_section_size = encoded_qname.size() + 4;
71
72 std::vector<char> request(sizeof(net::dns_protocol::Header) +
73 query_section_size);
74 base::BigEndianWriter writer(request.data(), request.size());
75
76 // Header
77 net::dns_protocol::Header header = {};
78 header.flags = base::HostToNet16(net::dns_protocol::kFlagRD);
79 header.qdcount = base::HostToNet16(1);
80 EXPECT_TRUE(writer.WriteBytes(&header, sizeof(header)));
81 // Query section
82 EXPECT_TRUE(writer.WriteBytes(encoded_qname.data(), encoded_qname.size()));
83 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kTypeTXT));
84 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kClassIN));
85 EXPECT_EQ(0, writer.remaining());
86
87 return request;
88 }
89
90 std::vector<char> CreateDnsTxtResponse(const std::vector<char>& request,
91 base::StringPiece answer) {
92 const size_t answers_section_size = 12 + answer.size();
93 constexpr uint32_t ttl = 86400; // seconds
94
95 std::vector<char> response(request.size() + answers_section_size);
96 std::copy(request.begin(), request.end(), response.begin());
97 // Modify the header
98 net::dns_protocol::Header* header =
99 reinterpret_cast<net::dns_protocol::Header*>(response.data());
100 header->ancount = base::HostToNet16(1);
101 header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse);
102
103 // Write the answer section
104 base::BigEndianWriter writer(response.data() + request.size(),
105 response.size() - request.size());
106 EXPECT_TRUE(writer.WriteU8(0xc0)); // qname is a pointer
107 EXPECT_TRUE(writer.WriteU8(
108 sizeof(*header))); // address of qname (start of query section)
109 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kTypeTXT));
110 EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kClassIN));
111 EXPECT_TRUE(writer.WriteU32(ttl));
112 EXPECT_TRUE(writer.WriteU16(answer.size()));
113 EXPECT_TRUE(writer.WriteBytes(answer.data(), answer.size()));
114 EXPECT_EQ(0, writer.remaining());
115
116 return response;
117 }
118
119 std::vector<char> CreateDnsErrorResponse(const std::vector<char>& request,
120 uint8_t rcode) {
121 std::vector<char> response(request);
122 // Modify the header
123 net::dns_protocol::Header* header =
124 reinterpret_cast<net::dns_protocol::Header*>(response.data());
125 header->ancount = base::HostToNet16(1);
126 header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse | rcode);
127
128 return response;
129 }
130
131 std::vector<std::string> GetSampleAuditProof(size_t length) {
132 std::vector<std::string> audit_proof(length);
133 // Makes each node of the audit proof different, so that tests are able to
134 // confirm that the audit proof is reconstructed in the correct order.
135 for (size_t i = 0; i < length; ++i) {
136 std::string node(crypto::kSHA256Length, '\0');
137 // Each node is 32 bytes, with each byte having a different value.
138 for (size_t j = 0; j < crypto::kSHA256Length; ++j) {
139 node[j] = static_cast<char>((-127 + i + j) % 128);
140 }
141 audit_proof[i].assign(std::move(node));
142 }
143
144 return audit_proof;
145 }
146
147 class MockLeafIndexCallback {
148 public:
149 MOCK_METHOD2(Run, void(int net_error, uint64_t leaf_index));
150 };
151
152 class MockAuditProofCallback {
153 public:
154 MOCK_METHOD2(Run_, void(int net_error, net::ct::MerkleAuditProof* proof));
155
156 // This proxy function is required because Chromium's GMock is not built with
157 // C++11 support (required for handling std::unique_ptr parameters).
158 // Remove it once this is rectified.
159 void Run(int net_error, std::unique_ptr<net::ct::MerkleAuditProof> proof) {
160 Run_(net_error, proof.release());
161 }
162 };
163
164 // A container for all of the data we need to keep alive for a mock socket.
165 // This is useful because Mock{Read,Write}, SequencedSocketData and
166 // MockClientSocketFactory all do not take ownership of or copy their arguments,
167 // so we have to manage the lifetime of those arguments ourselves. Wrapping all
168 // of that up in a single class simplifies this.
169 class MockSocket {
mmenke 2016/06/27 17:01:08 These aren't sockets. Call them MockSocketData or
Rob Percival 2016/06/27 19:01:18 Done.
170 public:
171 // A socket that expects one write and one read operation.
172 MockSocket(const std::vector<char>& write, const std::vector<char>& read)
173 : expected_write_payload_(write),
174 expected_read_payload_(read),
175 expected_write_(net::SYNCHRONOUS,
mmenke 2016/06/27 17:01:08 You should test net::ASYNC as well. For reads, es
Rob Percival 2016/06/27 19:01:18 Isn't that beyond the concern of LogDnsClient? It'
mmenke 2016/06/27 19:26:20 If DnsClient always returns asynchronously, regard
176 expected_write_payload_.data(),
177 expected_write_payload_.size(),
178 0),
179 expected_read_(net::SYNCHRONOUS,
180 expected_read_payload_.data(),
181 expected_read_payload_.size(),
182 1),
mmenke 2016/06/27 17:01:07 You can also simulate network errors for both read
Rob Percival 2016/06/28 21:44:54 Done.
183 socket_data_(&expected_read_, 1, &expected_write_, 1) {}
184
185 void AddToFactory(net::MockClientSocketFactory* socket_factory) {
186 socket_factory->AddSocketDataProvider(&socket_data_);
187 }
188
189 private:
190 const std::vector<char> expected_write_payload_;
191 const std::vector<char> expected_read_payload_;
192 net::MockWrite expected_write_;
193 net::MockRead expected_read_;
194 net::SequencedSocketData socket_data_;
195
196 DISALLOW_COPY_AND_ASSIGN(MockSocket);
197 };
198
199 class LogDnsClientTest : public ::testing::Test {
200 protected:
201 void SetUp() override {
202 thread_bundle_.reset(new content::TestBrowserThreadBundle(
203 content::TestBrowserThreadBundle::IO_MAINLOOP));
204 net_log_.reset(new net::BoundTestNetLog());
205 clock_.reset(new base::SimpleTestClock());
206
207 socket_factory_.reset(new net::MockClientSocketFactory());
208 mock_sockets_.clear();
mmenke 2016/06/27 17:01:07 Not needed. For each test, the test fixture is cr
Rob Percival 2016/06/27 19:01:18 Done.
209 }
210
211 std::unique_ptr<net::DnsClient> CreateDnsClient() {
212 net::DnsConfig config;
213 // Use an invalid nameserver address. This prevents the tests accidentally
214 // sending real DNS queries. The mock sockets don't care that the address
215 // is invalid.
216 config.nameservers.push_back(net::IPEndPoint());
217 // Don't attempt retransmissions - just fail.
218 config.attempts = 1;
219 // This ensures timeouts are long enough for memory tests.
220 config.timeout = TestTimeouts::action_timeout();
221 // Simplify testing - don't require random numbers for the source port.
222 // This means our FakeRandInt function should only be called to get query
223 // IDs.
224 config.randomize_ports = false;
225
226 std::unique_ptr<net::DnsClient> client =
227 net::DnsClient::CreateClientForTesting(net_log_->bound().net_log(),
228 socket_factory_.get(),
229 base::Bind(&FakeRandInt));
230 client->SetConfig(config);
231 return client;
232 }
233
234 void ExpectRequestAndResponse(base::StringPiece qname,
235 base::StringPiece answer) {
236 std::vector<char> request = CreateDnsTxtRequest(qname);
237 std::vector<char> response = CreateDnsTxtResponse(request, answer);
238
239 mock_sockets_.emplace_back(new MockSocket(request, response));
240 mock_sockets_.back()->AddToFactory(socket_factory_.get());
241 }
242
243 void ExpectRequestAndErrorResponse(base::StringPiece qname, uint8_t rcode) {
244 std::vector<char> request = CreateDnsTxtRequest(qname);
245 std::vector<char> response = CreateDnsErrorResponse(request, rcode);
246
247 mock_sockets_.emplace_back(new MockSocket(request, response));
248 mock_sockets_.back()->AddToFactory(socket_factory_.get());
249 }
250
251 void ExpectLeafIndexRequestAndResponse(base::StringPiece qname,
252 base::StringPiece leaf_index) {
253 // Prepend size to leaf_index to create the query answer (rdata)
254 ASSERT_LE(leaf_index.size(), 0xFFul); // size must fit into a single byte
255 std::string answer = leaf_index.as_string();
256 answer.insert(answer.begin(), static_cast<char>(leaf_index.size()));
257
258 ExpectRequestAndResponse(qname, answer);
259 }
260
261 void ExpectAuditProofRequestAndResponse(
262 base::StringPiece qname,
263 std::vector<std::string>::const_iterator audit_path_start,
264 std::vector<std::string>::const_iterator audit_path_end) {
265 // Join nodes in the audit path into a single string.
266 std::string proof =
267 std::accumulate(audit_path_start, audit_path_end, std::string());
268
269 // Prepend size to proof to create the query answer (rdata)
270 ASSERT_LE(proof.size(), 0xFFul); // size must fit into a single byte
271 proof.insert(proof.begin(), static_cast<char>(proof.size()));
272
273 ExpectRequestAndResponse(qname, proof);
274 }
275
276 void QueryLeafIndex(base::StringPiece log_domain,
277 base::StringPiece leaf_hash,
278 MockLeafIndexCallback* callback) {
279 std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient();
280 LogDnsClient log_client(std::move(dns_client), net_log_->bound(),
281 clock_.get());
282
283 LogDnsClient::LeafIndexCallback callback_func =
284 base::Bind(&MockLeafIndexCallback::Run, base::Unretained(callback));
285
286 log_client.QueryLeafIndex(log_domain, leaf_hash, callback_func);
287 base::RunLoop().RunUntilIdle();
mmenke 2016/06/27 17:01:08 I don't think it's a great idea, rather than waiti
Rob Percival 2016/06/27 19:01:18 Why's that? With your approach, if a bug causes th
mmenke 2016/06/27 19:26:20 Just because tests do it, doesn't mean they should
Rob Percival 2016/06/27 20:12:11 It's also the way TestBrowserThreadBundle gives as
mmenke 2016/06/27 20:24:45 I think it's unlikely, but remember that the Worke
Rob Percival 2016/06/28 21:44:54 Done.
288 }
289
290 void QueryAuditProof(base::StringPiece log_domain,
291 uint64_t leaf_index,
292 uint64_t tree_size,
293 MockAuditProofCallback* callback) {
294 std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient();
295 LogDnsClient log_client(std::move(dns_client), net_log_->bound(),
296 clock_.get());
297
298 LogDnsClient::AuditProofCallback callback_func =
299 base::Bind(&MockAuditProofCallback::Run, base::Unretained(callback));
300
301 log_client.QueryAuditProof(log_domain, leaf_index, tree_size,
302 callback_func);
303 base::RunLoop().RunUntilIdle();
304 }
305
306 std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle_;
307 std::unique_ptr<net::BoundTestNetLog> net_log_;
mmenke 2016/06/27 17:04:09 Also, you don't need this - just pass in a net::Bo
mmenke 2016/06/27 17:05:02 (Also, pass in nullptr when you need a NetLog inst
Rob Percival 2016/06/27 19:01:18 Done.
308 std::unique_ptr<base::SimpleTestClock> clock_;
309 std::vector<std::unique_ptr<MockSocket>> mock_sockets_;
310 std::unique_ptr<net::MockClientSocketFactory> socket_factory_;
311 };
312
313 TEST_F(LogDnsClientTest, QueryLeafIndex) {
314 ExpectLeafIndexRequestAndResponse(
315 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
316 "123456");
317
318 MockLeafIndexCallback callback;
mmenke 2016/06/27 17:01:08 The chrome wide preference is not to use gmock, to
Rob Percival 2016/06/27 19:01:18 As it happens, I used to have some hand-rolled moc
mmenke 2016/06/27 19:26:20 Clarity is generally better than being concise. H
Rob Percival 2016/06/27 20:12:11 That lack of support for unique_ptrs is indeed unf
Rob Percival 2016/06/28 21:44:54 Done.
319 EXPECT_CALL(callback, Run(IsNetOk(), 123456));
320
321 QueryLeafIndex("ct.test", kLeafHash, &callback);
322 }
323
324 TEST_F(LogDnsClientTest, QueryLeafIndexReportsThatLogDomainDoesNotExist) {
325 ExpectRequestAndErrorResponse(
326 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
327 net::dns_protocol::kRcodeNXDOMAIN);
328
329 MockLeafIndexCallback callback;
330 EXPECT_CALL(callback, Run(IsNetError(net::ERR_NAME_NOT_RESOLVED), 0));
331
332 QueryLeafIndex("ct.test", kLeafHash, &callback);
333 }
334
335 TEST_F(LogDnsClientTest, QueryLeafIndexReportsServerFailure) {
336 ExpectRequestAndErrorResponse(
337 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
338 net::dns_protocol::kRcodeSERVFAIL);
339
340 MockLeafIndexCallback callback;
341 EXPECT_CALL(callback, Run(IsNetError(net::ERR_DNS_SERVER_FAILED), 0));
342
343 QueryLeafIndex("ct.test", kLeafHash, &callback);
344 }
345
346 TEST_F(LogDnsClientTest, QueryLeafIndexReportsServerRefusal) {
347 ExpectRequestAndErrorResponse(
348 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
349 net::dns_protocol::kRcodeREFUSED);
350
351 MockLeafIndexCallback callback;
352 EXPECT_CALL(callback, Run(IsNetError(net::ERR_DNS_SERVER_FAILED), 0));
353
354 QueryLeafIndex("ct.test", kLeafHash, &callback);
355 }
356
357 TEST_F(LogDnsClientTest,
358 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsNotNumeric) {
359 ExpectLeafIndexRequestAndResponse(
360 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
361 "foo");
362
363 MockLeafIndexCallback callback;
364 EXPECT_CALL(callback, Run(IsNetError(net::ERR_DNS_MALFORMED_RESPONSE), 0));
365
366 QueryLeafIndex("ct.test", kLeafHash, &callback);
367 }
368
369 TEST_F(LogDnsClientTest,
370 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsFloatingPoint) {
371 ExpectLeafIndexRequestAndResponse(
372 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
373 "123456.0");
374
375 MockLeafIndexCallback callback;
376 EXPECT_CALL(callback, Run(IsNetError(net::ERR_DNS_MALFORMED_RESPONSE), 0));
377
378 QueryLeafIndex("ct.test", kLeafHash, &callback);
379 }
380
381 TEST_F(LogDnsClientTest,
382 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsEmpty) {
383 ExpectLeafIndexRequestAndResponse(
384 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", "");
385
386 MockLeafIndexCallback callback;
387 EXPECT_CALL(callback, Run(IsNetError(net::ERR_DNS_MALFORMED_RESPONSE), 0));
388
389 QueryLeafIndex("ct.test", kLeafHash, &callback);
390 }
391
392 TEST_F(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsEmpty) {
393 MockLeafIndexCallback callback;
394 EXPECT_CALL(callback, Run(IsNetError(net::ERR_INVALID_ARGUMENT), 0));
395
396 QueryLeafIndex("", kLeafHash, &callback);
397 }
398
399 TEST_F(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsNull) {
400 MockLeafIndexCallback callback;
401 EXPECT_CALL(callback, Run(IsNetError(net::ERR_INVALID_ARGUMENT), 0));
402
403 QueryLeafIndex(nullptr, kLeafHash, &callback);
404 }
405
406 TEST_F(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsInvalid) {
407 MockLeafIndexCallback callback;
408 EXPECT_CALL(callback, Run(IsNetError(net::ERR_INVALID_ARGUMENT), 0));
409
410 QueryLeafIndex("ct.test", "foo", &callback);
411 }
412
413 TEST_F(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsEmpty) {
414 MockLeafIndexCallback callback;
415 EXPECT_CALL(callback, Run(IsNetError(net::ERR_INVALID_ARGUMENT), 0));
416
417 QueryLeafIndex("ct.test", "", &callback);
418 }
419
420 TEST_F(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsNull) {
421 MockLeafIndexCallback callback;
422 EXPECT_CALL(callback, Run(IsNetError(net::ERR_INVALID_ARGUMENT), 0));
423
424 QueryLeafIndex("ct.test", nullptr, &callback);
425 }
426
427 TEST_F(LogDnsClientTest, QueryAuditProof) {
428 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
429
430 // It should require 3 queries to collect the entire audit proof, as there is
431 // only space for 7 nodes per UDP packet.
432 ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
433 audit_proof.begin(),
434 audit_proof.begin() + 7);
435 ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.",
436 audit_proof.begin() + 7,
437 audit_proof.begin() + 14);
438 ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.",
439 audit_proof.begin() + 14,
440 audit_proof.end());
441
442 MockAuditProofCallback callback;
443 EXPECT_CALL(callback,
444 Run_(IsNetOk(),
445 Pointee(AllOf(
446 Field(&net::ct::MerkleAuditProof::nodes, audit_proof),
447 Field(&net::ct::MerkleAuditProof::leaf_index, 123456)))))
448 .WillOnce(DeleteArg<1>());
449
450 QueryAuditProof("ct.test", 123456, 999999, &callback);
451 }
452
453 TEST_F(LogDnsClientTest,
454 QueryAuditProofHandlesResponsesWithEmptyAndShortAuditPaths) {
455 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
456
457 // Make some of the responses empty or contain fewer audit proof nodes than
458 // they can hold.
459 ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
460 audit_proof.begin(), audit_proof.begin());
461 ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
462 audit_proof.begin(),
463 audit_proof.begin() + 1);
464 ExpectAuditProofRequestAndResponse("1.123456.999999.tree.ct.test.",
465 audit_proof.begin() + 1,
466 audit_proof.begin() + 3);
467 ExpectAuditProofRequestAndResponse("3.123456.999999.tree.ct.test.",
468 audit_proof.begin() + 3,
469 audit_proof.begin() + 6);
470 ExpectAuditProofRequestAndResponse("6.123456.999999.tree.ct.test.",
471 audit_proof.begin() + 6,
472 audit_proof.begin() + 10);
473 ExpectAuditProofRequestAndResponse("10.123456.999999.tree.ct.test.",
474 audit_proof.begin() + 10,
475 audit_proof.begin() + 13);
476 ExpectAuditProofRequestAndResponse("13.123456.999999.tree.ct.test.",
477 audit_proof.begin() + 13,
478 audit_proof.end());
479
480 MockAuditProofCallback callback;
481 EXPECT_CALL(callback,
482 Run_(IsNetOk(),
483 Pointee(AllOf(
484 Field(&net::ct::MerkleAuditProof::nodes, audit_proof),
485 Field(&net::ct::MerkleAuditProof::leaf_index, 123456)))))
486 .WillOnce(DeleteArg<1>());
487
488 QueryAuditProof("ct.test", 123456, 999999, &callback);
489 }
490
491 TEST_F(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) {
492 ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.",
493 net::dns_protocol::kRcodeNXDOMAIN);
494
495 MockAuditProofCallback callback;
496 EXPECT_CALL(callback, Run_(IsNetError(net::ERR_NAME_NOT_RESOLVED), nullptr));
497
498 QueryAuditProof("ct.test", 123456, 999999, &callback);
499 }
500
501 TEST_F(LogDnsClientTest, QueryAuditProofReportsServerFailure) {
502 ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.",
503 net::dns_protocol::kRcodeSERVFAIL);
504
505 MockAuditProofCallback callback;
506 EXPECT_CALL(callback, Run_(IsNetError(net::ERR_DNS_SERVER_FAILED), nullptr));
507
508 QueryAuditProof("ct.test", 123456, 999999, &callback);
509 }
510
511 TEST_F(LogDnsClientTest, QueryAuditProofReportsServerRefusal) {
512 ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.",
513 net::dns_protocol::kRcodeREFUSED);
514
515 MockAuditProofCallback callback;
516 EXPECT_CALL(callback, Run_(IsNetError(net::ERR_DNS_SERVER_FAILED), nullptr));
517
518 QueryAuditProof("ct.test", 123456, 999999, &callback);
519 }
520
521 TEST_F(LogDnsClientTest,
522 QueryAuditProofReportsResponseMalformedIfNodeTooShort) {
523 // node is shorter than a SHA-256 hash (31 vs 32 bytes)
524 const std::vector<std::string> audit_proof(1, std::string(31, 'a'));
525
526 ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
527 audit_proof.begin(), audit_proof.end());
528
529 MockAuditProofCallback callback;
530 EXPECT_CALL(callback,
531 Run_(IsNetError(net::ERR_DNS_MALFORMED_RESPONSE), nullptr));
532
533 QueryAuditProof("ct.test", 123456, 999999, &callback);
534 }
535
536 TEST_F(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfNodeTooLong) {
537 // node is longer than a SHA-256 hash (33 vs 32 bytes)
538 const std::vector<std::string> audit_proof(1, std::string(33, 'a'));
539
540 ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
541 audit_proof.begin(), audit_proof.end());
542
543 MockAuditProofCallback callback;
544 EXPECT_CALL(callback,
545 Run_(IsNetError(net::ERR_DNS_MALFORMED_RESPONSE), nullptr));
546
547 QueryAuditProof("ct.test", 123456, 999999, &callback);
548 }
549
550 TEST_F(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsEmpty) {
551 MockAuditProofCallback callback;
552 EXPECT_CALL(callback, Run_(IsNetError(net::ERR_INVALID_ARGUMENT), nullptr));
553
554 QueryAuditProof("", 123456, 999999, &callback);
555 }
556
557 TEST_F(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsNull) {
558 MockAuditProofCallback callback;
559 EXPECT_CALL(callback, Run_(IsNetError(net::ERR_INVALID_ARGUMENT), nullptr));
560
561 QueryAuditProof(nullptr, 123456, 999999, &callback);
562 }
563
564 TEST_F(LogDnsClientTest,
565 QueryAuditProofReportInvalidArgIfLeafIndexEqualToTreeSize) {
566 MockAuditProofCallback callback;
567 EXPECT_CALL(callback, Run_(IsNetError(net::ERR_INVALID_ARGUMENT), nullptr));
568
569 QueryAuditProof("ct.test", 123456, 123456, &callback);
570 }
571
572 TEST_F(LogDnsClientTest,
573 QueryAuditProofReportInvalidArgIfLeafIndexGreaterThanTreeSize) {
574 MockAuditProofCallback callback;
575 EXPECT_CALL(callback, Run_(IsNetError(net::ERR_INVALID_ARGUMENT), nullptr));
576
577 QueryAuditProof("ct.test", 999999, 123456, &callback);
578 }
579
580 } // namespace
581 } // namespace certificate_transparency
OLDNEW
« no previous file with comments | « components/certificate_transparency/log_dns_client.cc ('k') | components/components_tests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698