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

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

Issue 2331923003: Allow LogDnsClient queries to be rate-limited (Closed)
Patch Set: Improves tests 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
« no previous file with comments | « components/certificate_transparency/log_dns_client.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/log_dns_client.h" 5 #include "components/certificate_transparency/log_dns_client.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/format_macros.h"
13 #include "base/memory/ptr_util.h"
12 #include "base/message_loop/message_loop.h" 14 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h" 15 #include "base/run_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/stringprintf.h"
14 #include "components/certificate_transparency/mock_log_dns_traffic.h" 18 #include "components/certificate_transparency/mock_log_dns_traffic.h"
15 #include "crypto/sha2.h" 19 #include "crypto/sha2.h"
16 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.h"
17 #include "net/cert/merkle_audit_proof.h" 21 #include "net/cert/merkle_audit_proof.h"
18 #include "net/cert/signed_certificate_timestamp.h" 22 #include "net/cert/signed_certificate_timestamp.h"
19 #include "net/dns/dns_client.h" 23 #include "net/dns/dns_client.h"
20 #include "net/dns/dns_config_service.h" 24 #include "net/dns/dns_config_service.h"
21 #include "net/dns/dns_protocol.h" 25 #include "net/dns/dns_protocol.h"
22 #include "net/log/net_log.h" 26 #include "net/log/net_log.h"
23 #include "net/test/gtest_util.h" 27 #include "net/test/gtest_util.h"
24 #include "testing/gmock/include/gmock/gmock.h" 28 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h" 29 #include "testing/gtest/include/gtest/gtest.h"
26 30
27 namespace certificate_transparency { 31 namespace certificate_transparency {
28 namespace { 32 namespace {
29 33
34 using ::testing::AllOf;
35 using ::testing::Eq;
30 using ::testing::IsEmpty; 36 using ::testing::IsEmpty;
31 using ::testing::IsNull; 37 using ::testing::IsNull;
38 using ::testing::Le;
32 using ::testing::Not; 39 using ::testing::Not;
33 using ::testing::NotNull; 40 using ::testing::NotNull;
34 using net::test::IsError; 41 using net::test::IsError;
35 using net::test::IsOk; 42 using net::test::IsOk;
36 43
37 constexpr char kLeafHash[] = 44 const char* kLeafHashes[] = {
38 "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8" 45 "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8"
39 "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04"; 46 "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04",
47 "\x2c\x26\xb4\x6b\x68\xff\xc6\x8f\xf9\x9b\x45\x3c\x1d\x30\x41\x34\x13\x42"
48 "\x2d\x70\x64\x83\xbf\xa0\xf9\x8a\x5e\x88\x62\x66\xe7\xae",
49 "\xfc\xde\x2b\x2e\xdb\xa5\x6b\xf4\x08\x60\x1f\xb7\x21\xfe\x9b\x5c\x33\x8d"
50 "\x10\xee\x42\x9e\xa0\x4f\xae\x55\x11\xb6\x8f\xbf\x8f\xb9",
51 };
52
53 // Assumes log domain is "ct.test"
54 const char* kBase32LeafHashes[] = {
55 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
56 "FQTLI23I77DI76M3IU6B2MCBGQJUELLQMSB37IHZRJPIQYTG46XA.hash.ct.test.",
57 "7TPCWLW3UVV7ICDAD63SD7U3LQZY2EHOIKPKAT5OKUI3ND57R64Q.hash.ct.test.",
58 };
59
60 // Leaf indices and tree sizes for use with above leaf hashes.
61 const uint64_t kLeafIndices[] = {0, 1, 2};
62 const uint64_t kTreeSizes[] = {100, 10000, 1000000};
63
64 // Only 7 audit proof nodes can fit into a DNS response, because they are sent
65 // in a TXT RDATA string, which has a maximum size of 255 bytes, and each node
66 // is a SHA-256 hash (32 bytes), i.e. (255 / 32) == 7.
67 // This means audit proofs consisting of more than 7 nodes require multiple DNS
68 // requests to retrieve.
69 const size_t kMaxProofNodesPerDnsResponse = 7;
40 70
41 std::vector<std::string> GetSampleAuditProof(size_t length) { 71 std::vector<std::string> GetSampleAuditProof(size_t length) {
42 std::vector<std::string> audit_proof(length); 72 std::vector<std::string> audit_proof(length);
43 // Makes each node of the audit proof different, so that tests are able to 73 // Makes each node of the audit proof different, so that tests are able to
44 // confirm that the audit proof is reconstructed in the correct order. 74 // confirm that the audit proof is reconstructed in the correct order.
45 for (size_t i = 0; i < length; ++i) { 75 for (size_t i = 0; i < length; ++i) {
46 std::string node(crypto::kSHA256Length, '\0'); 76 std::string node(crypto::kSHA256Length, '\0');
47 // Each node is 32 bytes, with each byte having a different value. 77 // Each node is 32 bytes, with each byte having a different value.
48 for (size_t j = 0; j < crypto::kSHA256Length; ++j) { 78 for (size_t j = 0; j < crypto::kSHA256Length; ++j) {
49 node[j] = static_cast<char>((-127 + i + j) % 128); 79 node[j] = static_cast<char>((-127 + i + j) % 128);
50 } 80 }
51 audit_proof[i].assign(std::move(node)); 81 audit_proof[i].assign(std::move(node));
52 } 82 }
53 83
54 return audit_proof; 84 return audit_proof;
55 } 85 }
56 86
57 class MockLeafIndexCallback { 87 class MockLeafIndexCallback {
58 public: 88 public:
59 MockLeafIndexCallback() : called_(false) {} 89 MockLeafIndexCallback() : called_(false) {}
60 90
61 bool called() const { return called_; } 91 bool called() const { return called_; }
62 int net_error() const { return net_error_; } 92 int net_error() const { return net_error_; }
63 uint64_t leaf_index() const { return leaf_index_; } 93 uint64_t leaf_index() const { return leaf_index_; }
64 94
65 void Run(int net_error, uint64_t leaf_index) { 95 void Run(int net_error, uint64_t leaf_index) {
66 EXPECT_TRUE(!called_); 96 EXPECT_TRUE(!called_) << "Callback invoked more than once";
Ryan Sleevi 2016/10/03 23:57:29 I don't believe these comments are useful.
Rob Percival 2016/10/04 15:27:53 Done.
67 called_ = true; 97 called_ = true;
68 net_error_ = net_error; 98 net_error_ = net_error;
69 leaf_index_ = leaf_index; 99 leaf_index_ = leaf_index;
70 run_loop_.Quit(); 100 run_loop_.Quit();
71 } 101 }
72 102
73 LogDnsClient::LeafIndexCallback AsCallback() { 103 LogDnsClient::LeafIndexCallback AsCallback() {
74 return base::Bind(&MockLeafIndexCallback::Run, base::Unretained(this)); 104 return base::Bind(&MockLeafIndexCallback::Run, base::Unretained(this));
75 } 105 }
76 106
77 void WaitUntilRun() { run_loop_.Run(); } 107 void WaitUntilRun() { run_loop_.Run(); }
78 108
79 private: 109 private:
80 bool called_; 110 bool called_;
81 int net_error_; 111 int net_error_;
82 uint64_t leaf_index_; 112 uint64_t leaf_index_;
83 base::RunLoop run_loop_; 113 base::RunLoop run_loop_;
84 }; 114 };
85 115
86 class MockAuditProofCallback { 116 class MockAuditProofCallback {
87 public: 117 public:
88 MockAuditProofCallback() : called_(false) {} 118 MockAuditProofCallback() : called_(false) {}
89 119
90 bool called() const { return called_; } 120 bool called() const { return called_; }
91 int net_error() const { return net_error_; } 121 int net_error() const { return net_error_; }
92 const net::ct::MerkleAuditProof* proof() const { return proof_.get(); } 122 const net::ct::MerkleAuditProof* proof() const { return proof_.get(); }
93 123
94 void Run(int net_error, std::unique_ptr<net::ct::MerkleAuditProof> proof) { 124 void Run(int net_error, std::unique_ptr<net::ct::MerkleAuditProof> proof) {
95 EXPECT_TRUE(!called_); 125 EXPECT_TRUE(!called_) << "Callback invoked more than once";
96 called_ = true; 126 called_ = true;
97 net_error_ = net_error; 127 net_error_ = net_error;
98 proof_ = std::move(proof); 128 proof_ = std::move(proof);
99 run_loop_.Quit(); 129 run_loop_.Quit();
100 } 130 }
101 131
102 LogDnsClient::AuditProofCallback AsCallback() { 132 LogDnsClient::AuditProofCallback AsCallback() {
103 return base::Bind(&MockAuditProofCallback::Run, base::Unretained(this)); 133 return base::Bind(&MockAuditProofCallback::Run, base::Unretained(this));
104 } 134 }
105 135
106 void WaitUntilRun() { run_loop_.Run(); } 136 void WaitUntilRun() { run_loop_.Run(); }
107 137
108 private: 138 private:
109 bool called_; 139 bool called_;
110 int net_error_; 140 int net_error_;
111 std::unique_ptr<net::ct::MerkleAuditProof> proof_; 141 std::unique_ptr<net::ct::MerkleAuditProof> proof_;
112 base::RunLoop run_loop_; 142 base::RunLoop run_loop_;
113 }; 143 };
114 144
115 class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { 145 class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> {
116 protected: 146 protected:
117 LogDnsClientTest() 147 LogDnsClientTest()
118 : network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) { 148 : network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) {
119 mock_dns_.SetSocketReadMode(GetParam()); 149 mock_dns_.SetSocketReadMode(GetParam());
120 mock_dns_.InitializeDnsConfig(); 150 mock_dns_.InitializeDnsConfig();
121 } 151 }
122 152
153 std::unique_ptr<LogDnsClient> CreateLogDnsClient(
154 size_t max_concurrent_queries) {
155 return base::MakeUnique<LogDnsClient>(mock_dns_.CreateDnsClient(),
156 net::NetLogWithSource(),
157 max_concurrent_queries);
158 }
159
160 void QueryLeafIndexAsync(LogDnsClient* log_client,
161 base::StringPiece log_domain,
162 const char leaf_hash[crypto::kSHA256Length],
163 const LogDnsClient::LeafIndexCallback& callback) {
164 log_client->QueryLeafIndex(log_domain, leaf_hash, callback);
165 }
166
167 // Convenience function for calling QueryLeafIndexAsync synchronously.
123 void QueryLeafIndex(base::StringPiece log_domain, 168 void QueryLeafIndex(base::StringPiece log_domain,
124 base::StringPiece leaf_hash, 169 const char leaf_hash[crypto::kSHA256Length],
125 MockLeafIndexCallback* callback) { 170 MockLeafIndexCallback* callback) {
126 LogDnsClient log_client(mock_dns_.CreateDnsClient(), 171 std::unique_ptr<LogDnsClient> log_client = CreateLogDnsClient(0);
127 net::NetLogWithSource()); 172 QueryLeafIndexAsync(log_client.get(), log_domain, leaf_hash,
128 log_client.QueryLeafIndex(log_domain, leaf_hash, callback->AsCallback()); 173 callback->AsCallback());
129 callback->WaitUntilRun(); 174 callback->WaitUntilRun();
130 } 175 }
131 176
177 void QueryAuditProofAsync(LogDnsClient* log_client,
178 base::StringPiece log_domain,
179 uint64_t leaf_index,
180 uint64_t tree_size,
181 const LogDnsClient::AuditProofCallback& callback) {
182 log_client->QueryAuditProof(log_domain, leaf_index, tree_size, callback);
183 }
184
185 // Convenience function for calling QueryAuditProofAsync synchronously.
132 void QueryAuditProof(base::StringPiece log_domain, 186 void QueryAuditProof(base::StringPiece log_domain,
133 uint64_t leaf_index, 187 uint64_t leaf_index,
134 uint64_t tree_size, 188 uint64_t tree_size,
135 MockAuditProofCallback* callback) { 189 MockAuditProofCallback* callback) {
136 LogDnsClient log_client(mock_dns_.CreateDnsClient(), 190 std::unique_ptr<LogDnsClient> log_client = CreateLogDnsClient(0);
137 net::NetLogWithSource()); 191 QueryAuditProofAsync(log_client.get(), log_domain, leaf_index, tree_size,
138 log_client.QueryAuditProof(log_domain, leaf_index, tree_size, 192 callback->AsCallback());
139 callback->AsCallback());
140 callback->WaitUntilRun(); 193 callback->WaitUntilRun();
141 } 194 }
142 195
143 // This will be the NetworkChangeNotifier singleton for the duration of the 196 // This will be the NetworkChangeNotifier singleton for the duration of the
144 // test. It is accessed statically by LogDnsClient. 197 // test. It is accessed statically by LogDnsClient.
145 std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; 198 std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
146 // Queues and handles asynchronous DNS tasks. Indirectly used by LogDnsClient, 199 // Queues and handles asynchronous DNS tasks. Indirectly used by LogDnsClient,
147 // the underlying net::DnsClient, and NetworkChangeNotifier. 200 // the underlying net::DnsClient, and NetworkChangeNotifier.
148 base::MessageLoopForIO message_loop_; 201 base::MessageLoopForIO message_loop_;
149 // Allows mock DNS sockets to be setup. 202 // Allows mock DNS sockets to be setup.
150 MockLogDnsTraffic mock_dns_; 203 MockLogDnsTraffic mock_dns_;
151 }; 204 };
152 205
153 TEST_P(LogDnsClientTest, QueryLeafIndex) { 206 TEST_P(LogDnsClientTest, QueryLeafIndex) {
154 mock_dns_.ExpectLeafIndexRequestAndResponse( 207 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], "123456");
155 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
156 "123456");
157 208
158 MockLeafIndexCallback callback; 209 MockLeafIndexCallback callback;
159 QueryLeafIndex("ct.test", kLeafHash, &callback); 210 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
160 ASSERT_TRUE(callback.called()); 211 ASSERT_TRUE(callback.called());
161 EXPECT_THAT(callback.net_error(), IsOk()); 212 EXPECT_THAT(callback.net_error(), IsOk());
162 EXPECT_THAT(callback.leaf_index(), 123456); 213 EXPECT_THAT(callback.leaf_index(), Eq(123456u));
163 } 214 }
164 215
165 TEST_P(LogDnsClientTest, QueryLeafIndexReportsThatLogDomainDoesNotExist) { 216 TEST_P(LogDnsClientTest, QueryLeafIndexReportsThatLogDomainDoesNotExist) {
166 mock_dns_.ExpectRequestAndErrorResponse( 217 mock_dns_.ExpectRequestAndErrorResponse(kBase32LeafHashes[0],
167 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 218 net::dns_protocol::kRcodeNXDOMAIN);
168 net::dns_protocol::kRcodeNXDOMAIN);
169 219
170 MockLeafIndexCallback callback; 220 MockLeafIndexCallback callback;
171 QueryLeafIndex("ct.test", kLeafHash, &callback); 221 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
172 ASSERT_TRUE(callback.called()); 222 ASSERT_TRUE(callback.called());
173 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); 223 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED));
174 EXPECT_THAT(callback.leaf_index(), 0); 224 EXPECT_THAT(callback.leaf_index(), Eq(0u));
175 } 225 }
176 226
177 TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerFailure) { 227 TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerFailure) {
178 mock_dns_.ExpectRequestAndErrorResponse( 228 mock_dns_.ExpectRequestAndErrorResponse(kBase32LeafHashes[0],
179 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 229 net::dns_protocol::kRcodeSERVFAIL);
180 net::dns_protocol::kRcodeSERVFAIL);
181 230
182 MockLeafIndexCallback callback; 231 MockLeafIndexCallback callback;
183 QueryLeafIndex("ct.test", kLeafHash, &callback); 232 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
184 ASSERT_TRUE(callback.called()); 233 ASSERT_TRUE(callback.called());
185 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); 234 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED));
186 EXPECT_THAT(callback.leaf_index(), 0); 235 EXPECT_THAT(callback.leaf_index(), Eq(0u));
187 } 236 }
188 237
189 TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerRefusal) { 238 TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerRefusal) {
190 mock_dns_.ExpectRequestAndErrorResponse( 239 mock_dns_.ExpectRequestAndErrorResponse(kBase32LeafHashes[0],
191 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 240 net::dns_protocol::kRcodeREFUSED);
192 net::dns_protocol::kRcodeREFUSED);
193 241
194 MockLeafIndexCallback callback; 242 MockLeafIndexCallback callback;
195 QueryLeafIndex("ct.test", kLeafHash, &callback); 243 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
196 ASSERT_TRUE(callback.called()); 244 ASSERT_TRUE(callback.called());
197 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); 245 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED));
198 EXPECT_THAT(callback.leaf_index(), 0); 246 EXPECT_THAT(callback.leaf_index(), Eq(0u));
199 } 247 }
200 248
201 TEST_P(LogDnsClientTest, 249 TEST_P(LogDnsClientTest,
202 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsNotNumeric) { 250 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsNotNumeric) {
203 mock_dns_.ExpectLeafIndexRequestAndResponse( 251 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], "foo");
204 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
205 "foo");
206 252
207 MockLeafIndexCallback callback; 253 MockLeafIndexCallback callback;
208 QueryLeafIndex("ct.test", kLeafHash, &callback); 254 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
209 ASSERT_TRUE(callback.called()); 255 ASSERT_TRUE(callback.called());
210 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); 256 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
211 EXPECT_THAT(callback.leaf_index(), 0); 257 EXPECT_THAT(callback.leaf_index(), Eq(0u));
212 } 258 }
213 259
214 TEST_P(LogDnsClientTest, 260 TEST_P(LogDnsClientTest,
215 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsFloatingPoint) { 261 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsFloatingPoint) {
216 mock_dns_.ExpectLeafIndexRequestAndResponse( 262 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], "123456.0");
217 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
218 "123456.0");
219 263
220 MockLeafIndexCallback callback; 264 MockLeafIndexCallback callback;
221 QueryLeafIndex("ct.test", kLeafHash, &callback); 265 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
222 ASSERT_TRUE(callback.called()); 266 ASSERT_TRUE(callback.called());
223 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); 267 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
224 EXPECT_THAT(callback.leaf_index(), 0); 268 EXPECT_THAT(callback.leaf_index(), Eq(0u));
225 } 269 }
226 270
227 TEST_P(LogDnsClientTest, 271 TEST_P(LogDnsClientTest,
228 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsEmpty) { 272 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsEmpty) {
229 mock_dns_.ExpectLeafIndexRequestAndResponse( 273 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], "");
230 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", "");
231 274
232 MockLeafIndexCallback callback; 275 MockLeafIndexCallback callback;
233 QueryLeafIndex("ct.test", kLeafHash, &callback); 276 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
234 ASSERT_TRUE(callback.called()); 277 ASSERT_TRUE(callback.called());
235 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); 278 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
236 EXPECT_THAT(callback.leaf_index(), 0); 279 EXPECT_THAT(callback.leaf_index(), Eq(0u));
237 } 280 }
238 281
239 TEST_P(LogDnsClientTest, 282 TEST_P(LogDnsClientTest,
240 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericPrefix) { 283 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericPrefix) {
241 mock_dns_.ExpectLeafIndexRequestAndResponse( 284 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0],
242 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 285 "foo123456");
243 "foo123456");
244 286
245 MockLeafIndexCallback callback; 287 MockLeafIndexCallback callback;
246 QueryLeafIndex("ct.test", kLeafHash, &callback); 288 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
247 ASSERT_TRUE(callback.called()); 289 ASSERT_TRUE(callback.called());
248 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); 290 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
249 EXPECT_THAT(callback.leaf_index(), 0); 291 EXPECT_THAT(callback.leaf_index(), Eq(0u));
250 } 292 }
251 293
252 TEST_P(LogDnsClientTest, 294 TEST_P(LogDnsClientTest,
253 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericSuffix) { 295 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericSuffix) {
254 mock_dns_.ExpectLeafIndexRequestAndResponse( 296 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0],
255 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 297 "123456foo");
256 "123456foo");
257 298
258 MockLeafIndexCallback callback; 299 MockLeafIndexCallback callback;
259 QueryLeafIndex("ct.test", kLeafHash, &callback); 300 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
260 ASSERT_TRUE(callback.called()); 301 ASSERT_TRUE(callback.called());
261 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); 302 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
262 EXPECT_THAT(callback.leaf_index(), 0); 303 EXPECT_THAT(callback.leaf_index(), Eq(0u));
263 } 304 }
264 305
265 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsEmpty) { 306 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsEmpty) {
266 MockLeafIndexCallback callback; 307 MockLeafIndexCallback callback;
267 QueryLeafIndex("", kLeafHash, &callback); 308 QueryLeafIndex("", kLeafHashes[0], &callback);
268 ASSERT_TRUE(callback.called()); 309 ASSERT_TRUE(callback.called());
269 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 310 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
270 EXPECT_THAT(callback.leaf_index(), 0); 311 EXPECT_THAT(callback.leaf_index(), Eq(0u));
271 } 312 }
272 313
273 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsNull) { 314 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsNull) {
274 MockLeafIndexCallback callback; 315 MockLeafIndexCallback callback;
275 QueryLeafIndex(nullptr, kLeafHash, &callback); 316 QueryLeafIndex(nullptr, kLeafHashes[0], &callback);
276 ASSERT_TRUE(callback.called()); 317 ASSERT_TRUE(callback.called());
277 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 318 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
278 EXPECT_THAT(callback.leaf_index(), 0); 319 EXPECT_THAT(callback.leaf_index(), Eq(0u));
279 } 320 }
280 321
281 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsInvalid) { 322 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsInvalid) {
282 MockLeafIndexCallback callback; 323 MockLeafIndexCallback callback;
283 QueryLeafIndex("ct.test", "foo", &callback); 324 QueryLeafIndex("ct.test", "foo", &callback);
284 ASSERT_TRUE(callback.called()); 325 ASSERT_TRUE(callback.called());
285 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 326 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
286 EXPECT_THAT(callback.leaf_index(), 0); 327 EXPECT_THAT(callback.leaf_index(), Eq(0u));
287 } 328 }
288 329
289 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsEmpty) { 330 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsEmpty) {
290 MockLeafIndexCallback callback; 331 MockLeafIndexCallback callback;
291 QueryLeafIndex("ct.test", "", &callback); 332 QueryLeafIndex("ct.test", "", &callback);
292 ASSERT_TRUE(callback.called()); 333 ASSERT_TRUE(callback.called());
293 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 334 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
294 EXPECT_THAT(callback.leaf_index(), 0); 335 EXPECT_THAT(callback.leaf_index(), Eq(0u));
295 } 336 }
296 337
297 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsNull) { 338 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsNull) {
298 MockLeafIndexCallback callback; 339 MockLeafIndexCallback callback;
299 QueryLeafIndex("ct.test", nullptr, &callback); 340 QueryLeafIndex("ct.test", nullptr, &callback);
300 ASSERT_TRUE(callback.called()); 341 ASSERT_TRUE(callback.called());
301 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 342 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
302 EXPECT_THAT(callback.leaf_index(), 0); 343 EXPECT_THAT(callback.leaf_index(), Eq(0u));
303 } 344 }
304 345
305 TEST_P(LogDnsClientTest, QueryLeafIndexReportsSocketError) { 346 TEST_P(LogDnsClientTest, QueryLeafIndexReportsSocketError) {
306 mock_dns_.ExpectRequestAndSocketError( 347 mock_dns_.ExpectRequestAndSocketError(kBase32LeafHashes[0],
307 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 348 net::ERR_CONNECTION_REFUSED);
308 net::ERR_CONNECTION_REFUSED);
309 349
310 MockLeafIndexCallback callback; 350 MockLeafIndexCallback callback;
311 QueryLeafIndex("ct.test", kLeafHash, &callback); 351 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
312 ASSERT_TRUE(callback.called()); 352 ASSERT_TRUE(callback.called());
313 EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); 353 EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED));
314 EXPECT_THAT(callback.leaf_index(), 0); 354 EXPECT_THAT(callback.leaf_index(), Eq(0u));
315 } 355 }
316 356
317 TEST_P(LogDnsClientTest, QueryLeafIndexReportsTimeout) { 357 TEST_P(LogDnsClientTest, QueryLeafIndexReportsTimeout) {
318 mock_dns_.ExpectRequestAndTimeout( 358 mock_dns_.ExpectRequestAndTimeout(kBase32LeafHashes[0]);
319 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.");
320 359
321 MockLeafIndexCallback callback; 360 MockLeafIndexCallback callback;
322 QueryLeafIndex("ct.test", kLeafHash, &callback); 361 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
323 ASSERT_TRUE(callback.called()); 362 ASSERT_TRUE(callback.called());
324 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); 363 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT));
325 EXPECT_THAT(callback.leaf_index(), 0); 364 EXPECT_THAT(callback.leaf_index(), Eq(0u));
326 } 365 }
327 366
328 TEST_P(LogDnsClientTest, QueryAuditProof) { 367 TEST_P(LogDnsClientTest, QueryAuditProof) {
329 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); 368 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
330 369
331 // It should require 3 queries to collect the entire audit proof, as there is 370 // It takes a number of DNS requests to retrieve the entire |audit_proof|
332 // only space for 7 nodes per UDP packet. 371 // (see |kMaxProofNodesPerDnsResponse|).
333 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", 372 for (size_t nodes_begin = 0; nodes_begin < audit_proof.size();
334 audit_proof.begin(), 373 nodes_begin += kMaxProofNodesPerDnsResponse) {
335 audit_proof.begin() + 7); 374 const size_t nodes_end = std::min(
336 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.", 375 nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size());
337 audit_proof.begin() + 7, 376
338 audit_proof.begin() + 14); 377 mock_dns_.ExpectAuditProofRequestAndResponse(
339 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.", 378 base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin),
340 audit_proof.begin() + 14, 379 audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end);
341 audit_proof.end()); 380 }
342 381
343 MockAuditProofCallback callback; 382 MockAuditProofCallback callback;
344 QueryAuditProof("ct.test", 123456, 999999, &callback); 383 QueryAuditProof("ct.test", 123456, 999999, &callback);
345 ASSERT_TRUE(callback.called()); 384 ASSERT_TRUE(callback.called());
346 EXPECT_THAT(callback.net_error(), IsOk()); 385 EXPECT_THAT(callback.net_error(), IsOk());
347 ASSERT_THAT(callback.proof(), NotNull()); 386 ASSERT_THAT(callback.proof(), NotNull());
348 EXPECT_THAT(callback.proof()->leaf_index, 123456); 387 EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u));
349 // EXPECT_THAT(callback.proof()->tree_size, 999999); 388 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
350 EXPECT_THAT(callback.proof()->nodes, audit_proof); 389 // EXPECT_THAT(callback.proof()->tree_size, Eq(999999));
390 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof));
351 } 391 }
352 392
353 TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) { 393 TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) {
354 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); 394 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
355 395
356 // Make some of the responses contain fewer proof nodes than they can hold. 396 // Make some of the responses contain fewer proof nodes than they can hold.
357 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", 397 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
358 audit_proof.begin(), 398 audit_proof.begin(),
359 audit_proof.begin() + 1); 399 audit_proof.begin() + 1);
360 mock_dns_.ExpectAuditProofRequestAndResponse("1.123456.999999.tree.ct.test.", 400 mock_dns_.ExpectAuditProofRequestAndResponse("1.123456.999999.tree.ct.test.",
(...skipping 10 matching lines...) Expand all
371 audit_proof.begin() + 13); 411 audit_proof.begin() + 13);
372 mock_dns_.ExpectAuditProofRequestAndResponse("13.123456.999999.tree.ct.test.", 412 mock_dns_.ExpectAuditProofRequestAndResponse("13.123456.999999.tree.ct.test.",
373 audit_proof.begin() + 13, 413 audit_proof.begin() + 13,
374 audit_proof.end()); 414 audit_proof.end());
375 415
376 MockAuditProofCallback callback; 416 MockAuditProofCallback callback;
377 QueryAuditProof("ct.test", 123456, 999999, &callback); 417 QueryAuditProof("ct.test", 123456, 999999, &callback);
378 ASSERT_TRUE(callback.called()); 418 ASSERT_TRUE(callback.called());
379 EXPECT_THAT(callback.net_error(), IsOk()); 419 EXPECT_THAT(callback.net_error(), IsOk());
380 ASSERT_THAT(callback.proof(), NotNull()); 420 ASSERT_THAT(callback.proof(), NotNull());
381 EXPECT_THAT(callback.proof()->leaf_index, 123456); 421 EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u));
382 // EXPECT_THAT(callback.proof()->tree_size, 999999); 422 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
383 EXPECT_THAT(callback.proof()->nodes, audit_proof); 423 // EXPECT_THAT(callback.proof()->tree_size, Eq(999999));
424 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof));
384 } 425 }
385 426
386 TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) { 427 TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) {
387 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", 428 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.",
388 net::dns_protocol::kRcodeNXDOMAIN); 429 net::dns_protocol::kRcodeNXDOMAIN);
389 430
390 MockAuditProofCallback callback; 431 MockAuditProofCallback callback;
391 QueryAuditProof("ct.test", 123456, 999999, &callback); 432 QueryAuditProof("ct.test", 123456, 999999, &callback);
392 ASSERT_TRUE(callback.called()); 433 ASSERT_TRUE(callback.called());
393 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); 434 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED));
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 MockAuditProofCallback callback; 550 MockAuditProofCallback callback;
510 QueryAuditProof("ct.test", 123456, 999999, &callback); 551 QueryAuditProof("ct.test", 123456, 999999, &callback);
511 ASSERT_TRUE(callback.called()); 552 ASSERT_TRUE(callback.called());
512 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); 553 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT));
513 EXPECT_THAT(callback.proof(), IsNull()); 554 EXPECT_THAT(callback.proof(), IsNull());
514 } 555 }
515 556
516 TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { 557 TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) {
517 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); 558 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient();
518 net::DnsClient* dns_client = tmp.get(); 559 net::DnsClient* dns_client = tmp.get();
519 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource()); 560 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource(), 0);
520 561
521 // Get the current DNS config, modify it and broadcast the update. 562 // Get the current DNS config, modify it and broadcast the update.
522 net::DnsConfig config(*dns_client->GetConfig()); 563 net::DnsConfig config(*dns_client->GetConfig());
523 ASSERT_NE(123, config.attempts); 564 ASSERT_NE(123, config.attempts);
524 config.attempts = 123; 565 config.attempts = 123;
525 mock_dns_.SetDnsConfig(config); 566 mock_dns_.SetDnsConfig(config);
526 567
527 // Let the DNS config change propogate. 568 // Let the DNS config change propogate.
528 base::RunLoop().RunUntilIdle(); 569 base::RunLoop().RunUntilIdle();
529 EXPECT_EQ(123, dns_client->GetConfig()->attempts); 570 EXPECT_EQ(123, dns_client->GetConfig()->attempts);
530 } 571 }
531 572
532 TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) { 573 TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) {
533 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); 574 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient();
534 net::DnsClient* dns_client = tmp.get(); 575 net::DnsClient* dns_client = tmp.get();
535 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource()); 576 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource(), 0);
536 577
537 // Get the current DNS config, modify it and broadcast the update. 578 // Get the current DNS config, modify it and broadcast the update.
538 net::DnsConfig config(*dns_client->GetConfig()); 579 net::DnsConfig config(*dns_client->GetConfig());
539 ASSERT_THAT(config.nameservers, Not(IsEmpty())); 580 ASSERT_THAT(config.nameservers, Not(IsEmpty()));
540 config.nameservers.clear(); // Makes config invalid 581 config.nameservers.clear(); // Makes config invalid
541 mock_dns_.SetDnsConfig(config); 582 mock_dns_.SetDnsConfig(config);
542 583
543 // Let the DNS config change propogate. 584 // Let the DNS config change propogate.
544 base::RunLoop().RunUntilIdle(); 585 base::RunLoop().RunUntilIdle();
545 EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty())); 586 EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty()));
546 } 587 }
547 588
589 TEST_P(LogDnsClientTest, CanPerformLeafIndexQueriesInParallel) {
590 // Test that leaf index queries can be performed in parallel.
591 constexpr size_t kNumOfParallelQueries = 3;
592 ASSERT_THAT(kNumOfParallelQueries, AllOf(Le(arraysize(kLeafHashes)),
593 Le(arraysize(kBase32LeafHashes))))
594 << "Not enough test data for this many parallel queries";
595
596 std::unique_ptr<LogDnsClient> log_client =
597 CreateLogDnsClient(kNumOfParallelQueries);
598 MockLeafIndexCallback callbacks[kNumOfParallelQueries];
599
600 // Expect multiple queries.
601 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
602 mock_dns_.ExpectLeafIndexRequestAndResponse(
603 kBase32LeafHashes[i], base::Uint64ToString(kLeafIndices[i]));
604 }
605
606 // Start the queries.
607 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
608 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[i],
609 callbacks[i].AsCallback());
610 }
611
612 // Wait for each query to complete and check its results.
613 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
614 MockLeafIndexCallback& callback = callbacks[i];
615 callback.WaitUntilRun();
616
617 SCOPED_TRACE(testing::Message() << "callbacks[" << i << "]");
618 ASSERT_TRUE(callback.called());
619 EXPECT_THAT(callback.net_error(), IsOk());
620 EXPECT_THAT(callback.leaf_index(), Eq(kLeafIndices[i]));
621 }
622 }
623
624 TEST_P(LogDnsClientTest, CanPerformAuditProofQueriesInParallel) {
625 // Check that 3 audit proof queries can be performed in parallel.
626 constexpr size_t kNumOfParallelQueries = 3;
627 ASSERT_THAT(kNumOfParallelQueries,
628 AllOf(Le(arraysize(kLeafIndices)), Le(arraysize(kTreeSizes))))
629 << "Not enough test data for this many parallel queries";
630
631 std::unique_ptr<LogDnsClient> log_client =
632 CreateLogDnsClient(kNumOfParallelQueries);
633 MockAuditProofCallback callbacks[kNumOfParallelQueries];
634
635 // Each query should require one more DNS request than the last.
636 // This helps to test that parallel queries do not intefere with each other,
637 // e.g. one query causing another to end prematurely.
638 std::vector<std::string> audit_proofs[kNumOfParallelQueries];
639 for (size_t query_i = 0; query_i < kNumOfParallelQueries; ++query_i) {
640 const size_t dns_requests_required = query_i + 1;
641 audit_proofs[query_i] = GetSampleAuditProof(dns_requests_required *
642 kMaxProofNodesPerDnsResponse);
643 }
644 // The most DNS requests that are made by any of the above N queries is N.
645 const size_t kMaxDnsRequestsPerQuery = kNumOfParallelQueries;
646
647 // Setup expectations for up to N DNS requests per query performed.
648 // All of the queries will be started at the same time, so expect the DNS
649 // requests and responses to be interleaved.
650 // NB:
651 // Ideally, the tests wouldn't require that the DNS requests sent by the
652 // parallel queries are interleaved. However, the mock socket framework does
653 // not provide a way to express this.
654 for (size_t dns_req_i = 0; dns_req_i < kMaxDnsRequestsPerQuery; ++dns_req_i) {
655 for (size_t query_i = 0; query_i < kNumOfParallelQueries; ++query_i) {
656 const std::vector<std::string>& proof = audit_proofs[query_i];
657 // Closed-open range of |proof| nodes that are expected in this response.
658 const size_t start_node = dns_req_i * 7;
659 const size_t end_node =
660 std::min(start_node + kMaxProofNodesPerDnsResponse, proof.size());
661
662 // If there are any nodes left, expect another request and response.
663 if (start_node < end_node) {
664 mock_dns_.ExpectAuditProofRequestAndResponse(
665 base::StringPrintf("%zu.%" PRIu64 ".%" PRIu64 ".tree.ct.test.",
666 start_node, kLeafIndices[query_i],
667 kTreeSizes[query_i]),
668 proof.begin() + start_node, proof.begin() + end_node);
669 }
670 }
671 }
672
673 // Start the queries.
674 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
675 QueryAuditProofAsync(log_client.get(), "ct.test", kLeafIndices[i],
676 kTreeSizes[i], callbacks[i].AsCallback());
677 }
678
679 // Wait for each query to complete and check its results.
680 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
681 MockAuditProofCallback& callback = callbacks[i];
682 callbacks[i].WaitUntilRun();
683
684 SCOPED_TRACE(testing::Message() << "callbacks[" << i << "]");
685 ASSERT_TRUE(callback.called());
686 EXPECT_THAT(callback.net_error(), IsOk());
687 ASSERT_THAT(callback.proof(), NotNull());
688 EXPECT_THAT(callback.proof()->leaf_index, Eq(kLeafIndices[i]));
689 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
690 // EXPECT_THAT(callback.proof()->tree_size, kTreeSizes[i]);
691 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proofs[i]));
692 }
693 }
694
695 TEST_P(LogDnsClientTest, CanPerformLeafIndexAndAuditProofQueriesInParallel) {
696 // Check that a leaf index and audit proof query can be performed in parallel.
697 constexpr size_t kNumOfParallelQueries = 2;
698 std::unique_ptr<LogDnsClient> log_client =
699 CreateLogDnsClient(kNumOfParallelQueries);
700 MockLeafIndexCallback leaf_index_callback;
701 MockAuditProofCallback audit_proof_callback;
702 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
703
704 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], "123456");
705
706 // It should require 3 requests to collect the entire audit proof, as there is
707 // only space for 7 nodes per TXT record. One node is 32 bytes long and the
708 // TXT RDATA can have a maximum length of 255 bytes (255 / 32).
709 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
710 audit_proof.begin(),
711 audit_proof.begin() + 7);
712 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.",
713 audit_proof.begin() + 7,
714 audit_proof.begin() + 14);
715 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.",
716 audit_proof.begin() + 14,
717 audit_proof.end());
718
719 // Start the queries.
720 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[0],
721 leaf_index_callback.AsCallback());
722 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
723 audit_proof_callback.AsCallback());
724
725 // Wait for the queries to complete, then check their results.
726 leaf_index_callback.WaitUntilRun();
727 audit_proof_callback.WaitUntilRun();
728
729 ASSERT_TRUE(leaf_index_callback.called());
730 EXPECT_THAT(leaf_index_callback.net_error(), IsOk());
731 EXPECT_THAT(leaf_index_callback.leaf_index(), Eq(123456u));
732
733 ASSERT_TRUE(audit_proof_callback.called());
734 EXPECT_THAT(audit_proof_callback.net_error(), IsOk());
735 ASSERT_THAT(audit_proof_callback.proof(), NotNull());
736 EXPECT_THAT(audit_proof_callback.proof()->leaf_index, Eq(123456u));
737 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
738 // EXPECT_THAT(audit_proof_callback.proof()->tree_size, Eq(999999));
739 EXPECT_THAT(audit_proof_callback.proof()->nodes, Eq(audit_proof));
740 }
741
742 TEST_P(LogDnsClientTest, CanBeThrottledToOneLeafIndexQueryAtATime) {
743 // Check that leaf index queries can be rate-limited to one at a time.
744 // The second query, initiated while the first is in progress, should fail.
745 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], "123456");
746
747 const size_t max_concurrent_queries = 1;
748 std::unique_ptr<LogDnsClient> log_client =
749 CreateLogDnsClient(max_concurrent_queries);
750
751 // Start the queries.
752 MockLeafIndexCallback callback1;
753 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[0],
754 callback1.AsCallback());
755 MockLeafIndexCallback callback2;
756 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[1],
757 callback2.AsCallback());
758
759 callback1.WaitUntilRun();
760 callback2.WaitUntilRun();
761
762 // Check that the first query succeeded.
763 ASSERT_TRUE(callback1.called());
764 EXPECT_THAT(callback1.net_error(), IsOk());
765 EXPECT_THAT(callback1.leaf_index(), Eq(123456u));
766
767 // Check that the second query failed.
768 ASSERT_TRUE(callback2.called());
769 EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED));
770 EXPECT_THAT(callback2.leaf_index(), Eq(0u));
771
772 // Try a third query, which should succeed now that the first is finished.
773 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[2], "666");
774
775 MockLeafIndexCallback callback3;
776 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[2],
777 callback3.AsCallback());
778
779 callback3.WaitUntilRun();
780
781 // Check that the third query succeeded.
782 ASSERT_TRUE(callback3.called());
783 EXPECT_THAT(callback3.net_error(), IsOk());
784 EXPECT_THAT(callback3.leaf_index(), Eq(666u));
785 }
786
787 TEST_P(LogDnsClientTest, CanBeThrottledToOneAuditProofQueryAtATime) {
788 // Check that audit proof queries can be rate-limited to one at a time.
789 // The second query, initiated while the first is in progress, should fail.
790 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
791
792 // It should require 3 requests to collect the entire audit proof, as there is
793 // only space for 7 nodes per TXT record. One node is 32 bytes long and the
794 // TXT RDATA can have a maximum length of 255 bytes (255 / 32).
795 // Rate limiting should not interfere with these requests.
796 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
797 audit_proof.begin(),
798 audit_proof.begin() + 7);
799 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.",
800 audit_proof.begin() + 7,
801 audit_proof.begin() + 14);
802 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.",
803 audit_proof.begin() + 14,
804 audit_proof.end());
805
806 const size_t max_concurrent_queries = 1;
807 std::unique_ptr<LogDnsClient> log_client =
808 CreateLogDnsClient(max_concurrent_queries);
809
810 // Start the queries.
811 MockAuditProofCallback callback1;
812 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
813 callback1.AsCallback());
814 MockAuditProofCallback callback2;
815 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
816 callback2.AsCallback());
817
818 callback1.WaitUntilRun();
819 callback2.WaitUntilRun();
820
821 // Check that the first query succeeded.
822 ASSERT_TRUE(callback1.called());
823 EXPECT_THAT(callback1.net_error(), IsOk());
824 ASSERT_THAT(callback1.proof(), NotNull());
825 EXPECT_THAT(callback1.proof()->leaf_index, Eq(123456u));
826 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
827 // EXPECT_THAT(callback1.proof()->tree_size, Eq(999999));
828 EXPECT_THAT(callback1.proof()->nodes, Eq(audit_proof));
829
830 // Check that the second query failed.
831 ASSERT_TRUE(callback2.called());
832 EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED));
833 EXPECT_THAT(callback2.proof(), IsNull());
834
835 // Try a third query, which should succeed now that the first is finished.
836 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
837 audit_proof.begin(),
838 audit_proof.begin() + 7);
839 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.",
840 audit_proof.begin() + 7,
841 audit_proof.begin() + 14);
842 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.",
843 audit_proof.begin() + 14,
844 audit_proof.end());
845
846 MockAuditProofCallback callback3;
847 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
848 callback3.AsCallback());
849
850 callback3.WaitUntilRun();
851
852 // Check that the third query succeeded.
853 ASSERT_TRUE(callback3.called());
854 EXPECT_THAT(callback3.net_error(), IsOk());
855 ASSERT_THAT(callback3.proof(), NotNull());
856 EXPECT_THAT(callback3.proof()->leaf_index, Eq(123456u));
857 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
858 // EXPECT_THAT(callback3.proof()->tree_size, Eq(999999));
859 EXPECT_THAT(callback3.proof()->nodes, Eq(audit_proof));
860 }
861
862 TEST_P(LogDnsClientTest, ThrottlingAppliesAcrossQueryTypes) {
863 // Check that queries can be rate-limited to one at a time, regardless of the
864 // type of query. The second query, initiated while the first is in progress,
865 // should fail.
866 mock_dns_.ExpectLeafIndexRequestAndResponse(
867 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
868 "123456");
869
870 const size_t max_concurrent_queries = 1;
871 std::unique_ptr<LogDnsClient> log_client =
872 CreateLogDnsClient(max_concurrent_queries);
873
874 // Start the queries.
875 MockLeafIndexCallback leaf_index_callback;
876 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[0],
877 leaf_index_callback.AsCallback());
878 MockAuditProofCallback audit_proof_callback;
879 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
880 audit_proof_callback.AsCallback());
881
882 leaf_index_callback.WaitUntilRun();
883 audit_proof_callback.WaitUntilRun();
884
885 // Check that the first query succeeded.
886 ASSERT_TRUE(leaf_index_callback.called());
887 EXPECT_THAT(leaf_index_callback.net_error(), IsOk());
888 EXPECT_THAT(leaf_index_callback.leaf_index(), Eq(123456u));
889
890 // Check that the second query failed.
891 ASSERT_TRUE(audit_proof_callback.called());
892 EXPECT_THAT(audit_proof_callback.net_error(),
893 IsError(net::ERR_TEMPORARILY_THROTTLED));
894 EXPECT_THAT(audit_proof_callback.proof(), IsNull());
895 }
896
548 INSTANTIATE_TEST_CASE_P(ReadMode, 897 INSTANTIATE_TEST_CASE_P(ReadMode,
549 LogDnsClientTest, 898 LogDnsClientTest,
550 ::testing::Values(net::IoMode::ASYNC, 899 ::testing::Values(net::IoMode::ASYNC,
551 net::IoMode::SYNCHRONOUS)); 900 net::IoMode::SYNCHRONOUS));
552 901
553 } // namespace 902 } // namespace
554 } // namespace certificate_transparency 903 } // namespace certificate_transparency
OLDNEW
« no previous file with comments | « components/certificate_transparency/log_dns_client.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698