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

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

Issue 2331923003: Allow LogDnsClient queries to be rate-limited (Closed)
Patch Set: Rebase 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/log_dns_client.h" 5 #include "components/certificate_transparency/log_dns_client.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <numeric> 8 #include <numeric>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/format_macros.h"
14 #include "base/memory/ptr_util.h"
13 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
14 #include "base/run_loop.h" 16 #include "base/run_loop.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/stringprintf.h"
15 #include "components/certificate_transparency/mock_log_dns_traffic.h" 19 #include "components/certificate_transparency/mock_log_dns_traffic.h"
16 #include "crypto/sha2.h" 20 #include "crypto/sha2.h"
17 #include "net/base/net_errors.h" 21 #include "net/base/net_errors.h"
18 #include "net/cert/merkle_audit_proof.h" 22 #include "net/cert/merkle_audit_proof.h"
19 #include "net/cert/signed_certificate_timestamp.h" 23 #include "net/cert/signed_certificate_timestamp.h"
20 #include "net/dns/dns_client.h" 24 #include "net/dns/dns_client.h"
21 #include "net/dns/dns_config_service.h" 25 #include "net/dns/dns_config_service.h"
22 #include "net/dns/dns_protocol.h" 26 #include "net/dns/dns_protocol.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[] = {
Ryan Sleevi 2016/10/07 15:46:23 const char* const
Rob Percival 2016/10/11 18:02:56 Done.
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[] = {
Ryan Sleevi 2016/10/07 15:46:23 const char* const
Rob Percival 2016/10/11 18:02:56 Done.
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_FALSE(called_);
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_FALSE(called_);
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.", 208
156 123456); 209 MockLeafIndexCallback callback;
157 210 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
158 MockLeafIndexCallback callback;
159 QueryLeafIndex("ct.test", kLeafHash, &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); 219
169 220 MockLeafIndexCallback callback;
170 MockLeafIndexCallback callback; 221 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
171 QueryLeafIndex("ct.test", kLeafHash, &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); 230
181 231 MockLeafIndexCallback callback;
182 MockLeafIndexCallback callback; 232 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
183 QueryLeafIndex("ct.test", kLeafHash, &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); 241
193 242 MockLeafIndexCallback callback;
194 MockLeafIndexCallback callback; 243 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
195 QueryLeafIndex("ct.test", kLeafHash, &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 QueryLeafIndexReportsMalformedResponseIfContainsNoStrings) { 250 QueryLeafIndexReportsMalformedResponseIfContainsNoStrings) {
203 mock_dns_.ExpectRequestAndResponse( 251 mock_dns_.ExpectRequestAndResponse(
204 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 252 kBase32LeafHashes[0],
205 std::vector<base::StringPiece>()); 253 std::vector<base::StringPiece>());
206 254
207 MockLeafIndexCallback callback; 255 MockLeafIndexCallback callback;
208 QueryLeafIndex("ct.test", kLeafHash, &callback); 256 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
209 ASSERT_TRUE(callback.called()); 257 ASSERT_TRUE(callback.called());
210 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); 258 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
211 EXPECT_THAT(callback.leaf_index(), 0); 259 EXPECT_THAT(callback.leaf_index(), Eq(0u));
212 } 260 }
213 261
214 TEST_P(LogDnsClientTest, 262 TEST_P(LogDnsClientTest,
215 QueryLeafIndexReportsMalformedResponseIfContainsMoreThanOneString) { 263 QueryLeafIndexReportsMalformedResponseIfContainsMoreThanOneString) {
216 mock_dns_.ExpectRequestAndResponse( 264 mock_dns_.ExpectRequestAndResponse(
217 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 265 kBase32LeafHashes[0],
218 {"123456", "7"}); 266 {"123456", "7"});
219 267
220 MockLeafIndexCallback callback; 268 MockLeafIndexCallback callback;
221 QueryLeafIndex("ct.test", kLeafHash, &callback); 269 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
222 ASSERT_TRUE(callback.called()); 270 ASSERT_TRUE(callback.called());
223 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); 271 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
224 EXPECT_THAT(callback.leaf_index(), 0); 272 EXPECT_THAT(callback.leaf_index(), Eq(0u));
225 } 273 }
226 274
227 TEST_P(LogDnsClientTest, 275 TEST_P(LogDnsClientTest,
228 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsNotNumeric) { 276 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsNotNumeric) {
229 mock_dns_.ExpectRequestAndResponse( 277 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {"foo"});
230 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 278
231 {"foo"}); 279 MockLeafIndexCallback callback;
232 280 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
233 MockLeafIndexCallback callback; 281 ASSERT_TRUE(callback.called());
234 QueryLeafIndex("ct.test", kLeafHash, &callback); 282 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
235 ASSERT_TRUE(callback.called()); 283 EXPECT_THAT(callback.leaf_index(), Eq(0u));
236 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
237 EXPECT_THAT(callback.leaf_index(), 0);
238 } 284 }
239 285
240 TEST_P(LogDnsClientTest, 286 TEST_P(LogDnsClientTest,
241 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsFloatingPoint) { 287 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsFloatingPoint) {
242 mock_dns_.ExpectRequestAndResponse( 288 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {"123456.0"});
243 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 289
244 {"123456.0"}); 290 MockLeafIndexCallback callback;
245 291 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
246 MockLeafIndexCallback callback; 292 ASSERT_TRUE(callback.called());
247 QueryLeafIndex("ct.test", kLeafHash, &callback); 293 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
248 ASSERT_TRUE(callback.called()); 294 EXPECT_THAT(callback.leaf_index(), Eq(0u));
249 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
250 EXPECT_THAT(callback.leaf_index(), 0);
251 } 295 }
252 296
253 TEST_P(LogDnsClientTest, 297 TEST_P(LogDnsClientTest,
254 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsEmpty) { 298 QueryLeafIndexReportsMalformedResponseIfLeafIndexIsEmpty) {
255 mock_dns_.ExpectRequestAndResponse( 299 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {""});
256 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 300
257 {""}); 301 MockLeafIndexCallback callback;
258 302 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
259 MockLeafIndexCallback callback; 303 ASSERT_TRUE(callback.called());
260 QueryLeafIndex("ct.test", kLeafHash, &callback); 304 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
261 ASSERT_TRUE(callback.called()); 305 EXPECT_THAT(callback.leaf_index(), Eq(0u));
262 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
263 EXPECT_THAT(callback.leaf_index(), 0);
264 } 306 }
265 307
266 TEST_P(LogDnsClientTest, 308 TEST_P(LogDnsClientTest,
267 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericPrefix) { 309 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericPrefix) {
268 mock_dns_.ExpectRequestAndResponse( 310 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {"foo123456"});
269 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 311
270 {"foo123456"}); 312 MockLeafIndexCallback callback;
271 313 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
272 MockLeafIndexCallback callback; 314 ASSERT_TRUE(callback.called());
273 QueryLeafIndex("ct.test", kLeafHash, &callback); 315 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
274 ASSERT_TRUE(callback.called()); 316 EXPECT_THAT(callback.leaf_index(), Eq(0u));
275 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
276 EXPECT_THAT(callback.leaf_index(), 0);
277 } 317 }
278 318
279 TEST_P(LogDnsClientTest, 319 TEST_P(LogDnsClientTest,
280 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericSuffix) { 320 QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericSuffix) {
281 mock_dns_.ExpectRequestAndResponse( 321 mock_dns_.ExpectRequestAndResponse(kBase32LeafHashes[0], {"123456foo"});
282 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 322
283 {"123456foo"}); 323 MockLeafIndexCallback callback;
284 324 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
285 MockLeafIndexCallback callback; 325 ASSERT_TRUE(callback.called());
286 QueryLeafIndex("ct.test", kLeafHash, &callback); 326 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
287 ASSERT_TRUE(callback.called()); 327 EXPECT_THAT(callback.leaf_index(), Eq(0u));
288 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE));
289 EXPECT_THAT(callback.leaf_index(), 0);
290 } 328 }
291 329
292 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsEmpty) { 330 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsEmpty) {
293 MockLeafIndexCallback callback; 331 MockLeafIndexCallback callback;
294 QueryLeafIndex("", kLeafHash, &callback); 332 QueryLeafIndex("", kLeafHashes[0], &callback);
295 ASSERT_TRUE(callback.called()); 333 ASSERT_TRUE(callback.called());
296 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 334 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
297 EXPECT_THAT(callback.leaf_index(), 0); 335 EXPECT_THAT(callback.leaf_index(), Eq(0u));
298 } 336 }
299 337
300 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsNull) { 338 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsNull) {
301 MockLeafIndexCallback callback; 339 MockLeafIndexCallback callback;
302 QueryLeafIndex(nullptr, kLeafHash, &callback); 340 QueryLeafIndex(nullptr, kLeafHashes[0], &callback);
303 ASSERT_TRUE(callback.called()); 341 ASSERT_TRUE(callback.called());
304 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 342 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
305 EXPECT_THAT(callback.leaf_index(), 0); 343 EXPECT_THAT(callback.leaf_index(), Eq(0u));
306 } 344 }
307 345
308 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsInvalid) { 346 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsInvalid) {
309 MockLeafIndexCallback callback; 347 MockLeafIndexCallback callback;
310 QueryLeafIndex("ct.test", "foo", &callback); 348 QueryLeafIndex("ct.test", "foo", &callback);
311 ASSERT_TRUE(callback.called()); 349 ASSERT_TRUE(callback.called());
312 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 350 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
313 EXPECT_THAT(callback.leaf_index(), 0); 351 EXPECT_THAT(callback.leaf_index(), Eq(0u));
314 } 352 }
315 353
316 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsEmpty) { 354 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsEmpty) {
317 MockLeafIndexCallback callback; 355 MockLeafIndexCallback callback;
318 QueryLeafIndex("ct.test", "", &callback); 356 QueryLeafIndex("ct.test", "", &callback);
319 ASSERT_TRUE(callback.called()); 357 ASSERT_TRUE(callback.called());
320 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 358 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
321 EXPECT_THAT(callback.leaf_index(), 0); 359 EXPECT_THAT(callback.leaf_index(), Eq(0u));
322 } 360 }
323 361
324 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsNull) { 362 TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsNull) {
325 MockLeafIndexCallback callback; 363 MockLeafIndexCallback callback;
326 QueryLeafIndex("ct.test", nullptr, &callback); 364 QueryLeafIndex("ct.test", nullptr, &callback);
327 ASSERT_TRUE(callback.called()); 365 ASSERT_TRUE(callback.called());
328 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); 366 EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT));
329 EXPECT_THAT(callback.leaf_index(), 0); 367 EXPECT_THAT(callback.leaf_index(), Eq(0u));
330 } 368 }
331 369
332 TEST_P(LogDnsClientTest, QueryLeafIndexReportsSocketError) { 370 TEST_P(LogDnsClientTest, QueryLeafIndexReportsSocketError) {
333 mock_dns_.ExpectRequestAndSocketError( 371 mock_dns_.ExpectRequestAndSocketError(kBase32LeafHashes[0],
334 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", 372 net::ERR_CONNECTION_REFUSED);
335 net::ERR_CONNECTION_REFUSED); 373
336 374 MockLeafIndexCallback callback;
337 MockLeafIndexCallback callback; 375 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
338 QueryLeafIndex("ct.test", kLeafHash, &callback);
339 ASSERT_TRUE(callback.called()); 376 ASSERT_TRUE(callback.called());
340 EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); 377 EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED));
341 EXPECT_THAT(callback.leaf_index(), 0); 378 EXPECT_THAT(callback.leaf_index(), Eq(0u));
342 } 379 }
343 380
344 TEST_P(LogDnsClientTest, QueryLeafIndexReportsTimeout) { 381 TEST_P(LogDnsClientTest, QueryLeafIndexReportsTimeout) {
345 mock_dns_.ExpectRequestAndTimeout( 382 mock_dns_.ExpectRequestAndTimeout(kBase32LeafHashes[0]);
346 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test."); 383
347 384 MockLeafIndexCallback callback;
348 MockLeafIndexCallback callback; 385 QueryLeafIndex("ct.test", kLeafHashes[0], &callback);
349 QueryLeafIndex("ct.test", kLeafHash, &callback);
350 ASSERT_TRUE(callback.called()); 386 ASSERT_TRUE(callback.called());
351 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); 387 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT));
352 EXPECT_THAT(callback.leaf_index(), 0); 388 EXPECT_THAT(callback.leaf_index(), Eq(0u));
353 } 389 }
354 390
355 TEST_P(LogDnsClientTest, QueryAuditProof) { 391 TEST_P(LogDnsClientTest, QueryAuditProof) {
356 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); 392 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
357 393
358 // It should require 3 queries to collect the entire audit proof, as there is 394 // It takes a number of DNS requests to retrieve the entire |audit_proof|
359 // only space for 7 nodes per UDP packet. 395 // (see |kMaxProofNodesPerDnsResponse|).
360 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", 396 for (size_t nodes_begin = 0; nodes_begin < audit_proof.size();
361 audit_proof.begin(), 397 nodes_begin += kMaxProofNodesPerDnsResponse) {
362 audit_proof.begin() + 7); 398 const size_t nodes_end = std::min(
363 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.", 399 nodes_begin + kMaxProofNodesPerDnsResponse, audit_proof.size());
364 audit_proof.begin() + 7, 400
365 audit_proof.begin() + 14); 401 mock_dns_.ExpectAuditProofRequestAndResponse(
366 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.", 402 base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin),
367 audit_proof.begin() + 14, 403 audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end);
368 audit_proof.end()); 404 }
369 405
370 MockAuditProofCallback callback; 406 MockAuditProofCallback callback;
371 QueryAuditProof("ct.test", 123456, 999999, &callback); 407 QueryAuditProof("ct.test", 123456, 999999, &callback);
372 ASSERT_TRUE(callback.called()); 408 ASSERT_TRUE(callback.called());
373 EXPECT_THAT(callback.net_error(), IsOk()); 409 EXPECT_THAT(callback.net_error(), IsOk());
374 ASSERT_THAT(callback.proof(), NotNull()); 410 ASSERT_THAT(callback.proof(), NotNull());
375 EXPECT_THAT(callback.proof()->leaf_index, 123456); 411 EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u));
376 // EXPECT_THAT(callback.proof()->tree_size, 999999); 412 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
377 EXPECT_THAT(callback.proof()->nodes, audit_proof); 413 // EXPECT_THAT(callback.proof()->tree_size, Eq(999999));
414 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof));
378 } 415 }
379 416
380 TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) { 417 TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) {
381 const std::vector<std::string> audit_proof = GetSampleAuditProof(20); 418 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
382 419
383 // Make some of the responses contain fewer proof nodes than they can hold. 420 // Make some of the responses contain fewer proof nodes than they can hold.
384 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", 421 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
385 audit_proof.begin(), 422 audit_proof.begin(),
386 audit_proof.begin() + 1); 423 audit_proof.begin() + 1);
387 mock_dns_.ExpectAuditProofRequestAndResponse("1.123456.999999.tree.ct.test.", 424 mock_dns_.ExpectAuditProofRequestAndResponse("1.123456.999999.tree.ct.test.",
(...skipping 10 matching lines...) Expand all
398 audit_proof.begin() + 13); 435 audit_proof.begin() + 13);
399 mock_dns_.ExpectAuditProofRequestAndResponse("13.123456.999999.tree.ct.test.", 436 mock_dns_.ExpectAuditProofRequestAndResponse("13.123456.999999.tree.ct.test.",
400 audit_proof.begin() + 13, 437 audit_proof.begin() + 13,
401 audit_proof.end()); 438 audit_proof.end());
402 439
403 MockAuditProofCallback callback; 440 MockAuditProofCallback callback;
404 QueryAuditProof("ct.test", 123456, 999999, &callback); 441 QueryAuditProof("ct.test", 123456, 999999, &callback);
405 ASSERT_TRUE(callback.called()); 442 ASSERT_TRUE(callback.called());
406 EXPECT_THAT(callback.net_error(), IsOk()); 443 EXPECT_THAT(callback.net_error(), IsOk());
407 ASSERT_THAT(callback.proof(), NotNull()); 444 ASSERT_THAT(callback.proof(), NotNull());
408 EXPECT_THAT(callback.proof()->leaf_index, 123456); 445 EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u));
409 // EXPECT_THAT(callback.proof()->tree_size, 999999); 446 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
410 EXPECT_THAT(callback.proof()->nodes, audit_proof); 447 // EXPECT_THAT(callback.proof()->tree_size, Eq(999999));
448 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof));
411 } 449 }
412 450
413 TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) { 451 TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) {
414 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", 452 mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.",
415 net::dns_protocol::kRcodeNXDOMAIN); 453 net::dns_protocol::kRcodeNXDOMAIN);
416 454
417 MockAuditProofCallback callback; 455 MockAuditProofCallback callback;
418 QueryAuditProof("ct.test", 123456, 999999, &callback); 456 QueryAuditProof("ct.test", 123456, 999999, &callback);
419 ASSERT_TRUE(callback.called()); 457 ASSERT_TRUE(callback.called());
420 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); 458 EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED));
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 MockAuditProofCallback callback; 608 MockAuditProofCallback callback;
571 QueryAuditProof("ct.test", 123456, 999999, &callback); 609 QueryAuditProof("ct.test", 123456, 999999, &callback);
572 ASSERT_TRUE(callback.called()); 610 ASSERT_TRUE(callback.called());
573 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); 611 EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT));
574 EXPECT_THAT(callback.proof(), IsNull()); 612 EXPECT_THAT(callback.proof(), IsNull());
575 } 613 }
576 614
577 TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { 615 TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) {
578 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); 616 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient();
579 net::DnsClient* dns_client = tmp.get(); 617 net::DnsClient* dns_client = tmp.get();
580 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource()); 618 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource(), 0);
581 619
582 // Get the current DNS config, modify it and broadcast the update. 620 // Get the current DNS config, modify it and broadcast the update.
583 net::DnsConfig config(*dns_client->GetConfig()); 621 net::DnsConfig config(*dns_client->GetConfig());
584 ASSERT_NE(123, config.attempts); 622 ASSERT_NE(123, config.attempts);
585 config.attempts = 123; 623 config.attempts = 123;
586 mock_dns_.SetDnsConfig(config); 624 mock_dns_.SetDnsConfig(config);
587 625
588 // Let the DNS config change propogate. 626 // Let the DNS config change propogate.
589 base::RunLoop().RunUntilIdle(); 627 base::RunLoop().RunUntilIdle();
590 EXPECT_EQ(123, dns_client->GetConfig()->attempts); 628 EXPECT_EQ(123, dns_client->GetConfig()->attempts);
591 } 629 }
592 630
593 TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) { 631 TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) {
594 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); 632 std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient();
595 net::DnsClient* dns_client = tmp.get(); 633 net::DnsClient* dns_client = tmp.get();
596 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource()); 634 LogDnsClient log_client(std::move(tmp), net::NetLogWithSource(), 0);
597 635
598 // Get the current DNS config, modify it and broadcast the update. 636 // Get the current DNS config, modify it and broadcast the update.
599 net::DnsConfig config(*dns_client->GetConfig()); 637 net::DnsConfig config(*dns_client->GetConfig());
600 ASSERT_THAT(config.nameservers, Not(IsEmpty())); 638 ASSERT_THAT(config.nameservers, Not(IsEmpty()));
601 config.nameservers.clear(); // Makes config invalid 639 config.nameservers.clear(); // Makes config invalid
602 mock_dns_.SetDnsConfig(config); 640 mock_dns_.SetDnsConfig(config);
603 641
604 // Let the DNS config change propogate. 642 // Let the DNS config change propogate.
605 base::RunLoop().RunUntilIdle(); 643 base::RunLoop().RunUntilIdle();
606 EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty())); 644 EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty()));
607 } 645 }
608 646
647 TEST_P(LogDnsClientTest, CanPerformLeafIndexQueriesInParallel) {
648 // Test that leaf index queries can be performed in parallel.
649 constexpr size_t kNumOfParallelQueries = 3;
650 ASSERT_THAT(kNumOfParallelQueries, AllOf(Le(arraysize(kLeafHashes)),
651 Le(arraysize(kBase32LeafHashes))))
652 << "Not enough test data for this many parallel queries";
653
654 std::unique_ptr<LogDnsClient> log_client =
655 CreateLogDnsClient(kNumOfParallelQueries);
656 MockLeafIndexCallback callbacks[kNumOfParallelQueries];
657
658 // Expect multiple queries.
659 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
660 mock_dns_.ExpectLeafIndexRequestAndResponse(
661 kBase32LeafHashes[i], kLeafIndices[i]);
662 }
663
664 // Start the queries.
665 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
666 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[i],
667 callbacks[i].AsCallback());
668 }
669
670 // Wait for each query to complete and check its results.
671 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
672 MockLeafIndexCallback& callback = callbacks[i];
673 callback.WaitUntilRun();
674
675 SCOPED_TRACE(testing::Message() << "callbacks[" << i << "]");
676 ASSERT_TRUE(callback.called());
677 EXPECT_THAT(callback.net_error(), IsOk());
678 EXPECT_THAT(callback.leaf_index(), Eq(kLeafIndices[i]));
679 }
680 }
681
682 TEST_P(LogDnsClientTest, CanPerformAuditProofQueriesInParallel) {
683 // Check that 3 audit proof queries can be performed in parallel.
684 constexpr size_t kNumOfParallelQueries = 3;
685 ASSERT_THAT(kNumOfParallelQueries,
686 AllOf(Le(arraysize(kLeafIndices)), Le(arraysize(kTreeSizes))))
687 << "Not enough test data for this many parallel queries";
688
689 std::unique_ptr<LogDnsClient> log_client =
690 CreateLogDnsClient(kNumOfParallelQueries);
691 MockAuditProofCallback callbacks[kNumOfParallelQueries];
692
693 // Each query should require one more DNS request than the last.
694 // This helps to test that parallel queries do not intefere with each other,
695 // e.g. one query causing another to end prematurely.
696 std::vector<std::string> audit_proofs[kNumOfParallelQueries];
697 for (size_t query_i = 0; query_i < kNumOfParallelQueries; ++query_i) {
698 const size_t dns_requests_required = query_i + 1;
699 audit_proofs[query_i] = GetSampleAuditProof(dns_requests_required *
700 kMaxProofNodesPerDnsResponse);
701 }
702 // The most DNS requests that are made by any of the above N queries is N.
703 const size_t kMaxDnsRequestsPerQuery = kNumOfParallelQueries;
704
705 // Setup expectations for up to N DNS requests per query performed.
706 // All of the queries will be started at the same time, so expect the DNS
707 // requests and responses to be interleaved.
708 // NB:
709 // Ideally, the tests wouldn't require that the DNS requests sent by the
710 // parallel queries are interleaved. However, the mock socket framework does
711 // not provide a way to express this.
712 for (size_t dns_req_i = 0; dns_req_i < kMaxDnsRequestsPerQuery; ++dns_req_i) {
713 for (size_t query_i = 0; query_i < kNumOfParallelQueries; ++query_i) {
714 const std::vector<std::string>& proof = audit_proofs[query_i];
715 // Closed-open range of |proof| nodes that are expected in this response.
716 const size_t start_node = dns_req_i * 7;
717 const size_t end_node =
718 std::min(start_node + kMaxProofNodesPerDnsResponse, proof.size());
719
720 // If there are any nodes left, expect another request and response.
721 if (start_node < end_node) {
722 mock_dns_.ExpectAuditProofRequestAndResponse(
723 base::StringPrintf("%zu.%" PRIu64 ".%" PRIu64 ".tree.ct.test.",
724 start_node, kLeafIndices[query_i],
725 kTreeSizes[query_i]),
726 proof.begin() + start_node, proof.begin() + end_node);
727 }
728 }
729 }
730
731 // Start the queries.
732 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
733 QueryAuditProofAsync(log_client.get(), "ct.test", kLeafIndices[i],
734 kTreeSizes[i], callbacks[i].AsCallback());
735 }
736
737 // Wait for each query to complete and check its results.
738 for (size_t i = 0; i < kNumOfParallelQueries; ++i) {
739 MockAuditProofCallback& callback = callbacks[i];
740 callbacks[i].WaitUntilRun();
741
742 SCOPED_TRACE(testing::Message() << "callbacks[" << i << "]");
743 ASSERT_TRUE(callback.called());
744 EXPECT_THAT(callback.net_error(), IsOk());
745 ASSERT_THAT(callback.proof(), NotNull());
746 EXPECT_THAT(callback.proof()->leaf_index, Eq(kLeafIndices[i]));
747 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
748 // EXPECT_THAT(callback.proof()->tree_size, kTreeSizes[i]);
749 EXPECT_THAT(callback.proof()->nodes, Eq(audit_proofs[i]));
750 }
751 }
752
753 TEST_P(LogDnsClientTest, CanPerformLeafIndexAndAuditProofQueriesInParallel) {
754 // Check that a leaf index and audit proof query can be performed in parallel.
755 constexpr size_t kNumOfParallelQueries = 2;
756 std::unique_ptr<LogDnsClient> log_client =
757 CreateLogDnsClient(kNumOfParallelQueries);
758 MockLeafIndexCallback leaf_index_callback;
759 MockAuditProofCallback audit_proof_callback;
760 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
761
762 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], 123456);
763
764 // It should require 3 requests to collect the entire audit proof, as there is
765 // only space for 7 nodes per TXT record. One node is 32 bytes long and the
766 // TXT RDATA can have a maximum length of 255 bytes (255 / 32).
767 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
768 audit_proof.begin(),
769 audit_proof.begin() + 7);
770 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.",
771 audit_proof.begin() + 7,
772 audit_proof.begin() + 14);
773 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.",
774 audit_proof.begin() + 14,
775 audit_proof.end());
776
777 // Start the queries.
778 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[0],
779 leaf_index_callback.AsCallback());
780 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
781 audit_proof_callback.AsCallback());
782
783 // Wait for the queries to complete, then check their results.
784 leaf_index_callback.WaitUntilRun();
785 audit_proof_callback.WaitUntilRun();
786
787 ASSERT_TRUE(leaf_index_callback.called());
788 EXPECT_THAT(leaf_index_callback.net_error(), IsOk());
789 EXPECT_THAT(leaf_index_callback.leaf_index(), Eq(123456u));
790
791 ASSERT_TRUE(audit_proof_callback.called());
792 EXPECT_THAT(audit_proof_callback.net_error(), IsOk());
793 ASSERT_THAT(audit_proof_callback.proof(), NotNull());
794 EXPECT_THAT(audit_proof_callback.proof()->leaf_index, Eq(123456u));
795 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
796 // EXPECT_THAT(audit_proof_callback.proof()->tree_size, Eq(999999));
797 EXPECT_THAT(audit_proof_callback.proof()->nodes, Eq(audit_proof));
798 }
799
800 TEST_P(LogDnsClientTest, CanBeThrottledToOneLeafIndexQueryAtATime) {
801 // Check that leaf index queries can be rate-limited to one at a time.
802 // The second query, initiated while the first is in progress, should fail.
803 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[0], 123456);
804
805 const size_t max_concurrent_queries = 1;
806 std::unique_ptr<LogDnsClient> log_client =
807 CreateLogDnsClient(max_concurrent_queries);
808
809 // Start the queries.
810 MockLeafIndexCallback callback1;
811 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[0],
812 callback1.AsCallback());
813 MockLeafIndexCallback callback2;
814 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[1],
815 callback2.AsCallback());
816
817 callback1.WaitUntilRun();
818 callback2.WaitUntilRun();
819
820 // Check that the first query succeeded.
821 ASSERT_TRUE(callback1.called());
822 EXPECT_THAT(callback1.net_error(), IsOk());
823 EXPECT_THAT(callback1.leaf_index(), Eq(123456u));
824
825 // Check that the second query failed.
826 ASSERT_TRUE(callback2.called());
827 EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED));
828 EXPECT_THAT(callback2.leaf_index(), Eq(0u));
829
830 // Try a third query, which should succeed now that the first is finished.
831 mock_dns_.ExpectLeafIndexRequestAndResponse(kBase32LeafHashes[2], 666);
832
833 MockLeafIndexCallback callback3;
834 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[2],
835 callback3.AsCallback());
836
837 callback3.WaitUntilRun();
838
839 // Check that the third query succeeded.
840 ASSERT_TRUE(callback3.called());
841 EXPECT_THAT(callback3.net_error(), IsOk());
842 EXPECT_THAT(callback3.leaf_index(), Eq(666u));
843 }
844
845 TEST_P(LogDnsClientTest, CanBeThrottledToOneAuditProofQueryAtATime) {
846 // Check that audit proof queries can be rate-limited to one at a time.
847 // The second query, initiated while the first is in progress, should fail.
848 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
849
850 // It should require 3 requests to collect the entire audit proof, as there is
851 // only space for 7 nodes per TXT record. One node is 32 bytes long and the
852 // TXT RDATA can have a maximum length of 255 bytes (255 / 32).
853 // Rate limiting should not interfere with these requests.
854 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
855 audit_proof.begin(),
856 audit_proof.begin() + 7);
857 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.",
858 audit_proof.begin() + 7,
859 audit_proof.begin() + 14);
860 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.",
861 audit_proof.begin() + 14,
862 audit_proof.end());
863
864 const size_t max_concurrent_queries = 1;
865 std::unique_ptr<LogDnsClient> log_client =
866 CreateLogDnsClient(max_concurrent_queries);
867
868 // Start the queries.
869 MockAuditProofCallback callback1;
870 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
871 callback1.AsCallback());
872 MockAuditProofCallback callback2;
873 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
874 callback2.AsCallback());
875
876 callback1.WaitUntilRun();
877 callback2.WaitUntilRun();
878
879 // Check that the first query succeeded.
880 ASSERT_TRUE(callback1.called());
881 EXPECT_THAT(callback1.net_error(), IsOk());
882 ASSERT_THAT(callback1.proof(), NotNull());
883 EXPECT_THAT(callback1.proof()->leaf_index, Eq(123456u));
884 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
885 // EXPECT_THAT(callback1.proof()->tree_size, Eq(999999));
886 EXPECT_THAT(callback1.proof()->nodes, Eq(audit_proof));
887
888 // Check that the second query failed.
889 ASSERT_TRUE(callback2.called());
890 EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED));
891 EXPECT_THAT(callback2.proof(), IsNull());
892
893 // Try a third query, which should succeed now that the first is finished.
894 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
895 audit_proof.begin(),
896 audit_proof.begin() + 7);
897 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.",
898 audit_proof.begin() + 7,
899 audit_proof.begin() + 14);
900 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.",
901 audit_proof.begin() + 14,
902 audit_proof.end());
903
904 MockAuditProofCallback callback3;
905 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
906 callback3.AsCallback());
907
908 callback3.WaitUntilRun();
909
910 // Check that the third query succeeded.
911 ASSERT_TRUE(callback3.called());
912 EXPECT_THAT(callback3.net_error(), IsOk());
913 ASSERT_THAT(callback3.proof(), NotNull());
914 EXPECT_THAT(callback3.proof()->leaf_index, Eq(123456u));
915 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
916 // EXPECT_THAT(callback3.proof()->tree_size, Eq(999999));
917 EXPECT_THAT(callback3.proof()->nodes, Eq(audit_proof));
918 }
919
920 TEST_P(LogDnsClientTest, ThrottlingAppliesAcrossQueryTypes) {
921 // Check that queries can be rate-limited to one at a time, regardless of the
922 // type of query. The second query, initiated while the first is in progress,
923 // should fail.
924 mock_dns_.ExpectLeafIndexRequestAndResponse(
925 "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
926 123456);
927
928 const size_t max_concurrent_queries = 1;
929 std::unique_ptr<LogDnsClient> log_client =
930 CreateLogDnsClient(max_concurrent_queries);
931
932 // Start the queries.
933 MockLeafIndexCallback leaf_index_callback;
934 QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHashes[0],
935 leaf_index_callback.AsCallback());
936 MockAuditProofCallback audit_proof_callback;
937 QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999,
938 audit_proof_callback.AsCallback());
939
940 leaf_index_callback.WaitUntilRun();
941 audit_proof_callback.WaitUntilRun();
942
943 // Check that the first query succeeded.
944 ASSERT_TRUE(leaf_index_callback.called());
945 EXPECT_THAT(leaf_index_callback.net_error(), IsOk());
946 EXPECT_THAT(leaf_index_callback.leaf_index(), Eq(123456u));
947
948 // Check that the second query failed.
949 ASSERT_TRUE(audit_proof_callback.called());
950 EXPECT_THAT(audit_proof_callback.net_error(),
951 IsError(net::ERR_TEMPORARILY_THROTTLED));
952 EXPECT_THAT(audit_proof_callback.proof(), IsNull());
953 }
954
609 INSTANTIATE_TEST_CASE_P(ReadMode, 955 INSTANTIATE_TEST_CASE_P(ReadMode,
610 LogDnsClientTest, 956 LogDnsClientTest,
611 ::testing::Values(net::IoMode::ASYNC, 957 ::testing::Values(net::IoMode::ASYNC,
612 net::IoMode::SYNCHRONOUS)); 958 net::IoMode::SYNCHRONOUS));
613 959
614 } // namespace 960 } // namespace
615 } // namespace certificate_transparency 961 } // namespace certificate_transparency
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698