Chromium Code Reviews| Index: components/certificate_transparency/log_dns_client_unittest.cc |
| diff --git a/components/certificate_transparency/log_dns_client_unittest.cc b/components/certificate_transparency/log_dns_client_unittest.cc |
| index 64223ef51757768878acef01f6fd8431449782c9..4875d9df90da3d6b9aa29af9b40825de3c18cffa 100644 |
| --- a/components/certificate_transparency/log_dns_client_unittest.cc |
| +++ b/components/certificate_transparency/log_dns_client_unittest.cc |
| @@ -9,6 +9,7 @@ |
| #include <utility> |
| #include <vector> |
| +#include "base/memory/ptr_util.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| #include "components/certificate_transparency/mock_log_dns_traffic.h" |
| @@ -27,6 +28,7 @@ |
| namespace certificate_transparency { |
| namespace { |
| +using ::testing::Eq; |
| using ::testing::IsEmpty; |
| using ::testing::IsNull; |
| using ::testing::Not; |
| @@ -120,21 +122,46 @@ class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { |
| mock_dns_.InitializeDnsConfig(); |
| } |
| + std::unique_ptr<LogDnsClient> CreateLogDnsClient( |
| + size_t max_concurrent_queries) { |
| + return base::MakeUnique<LogDnsClient>(mock_dns_.CreateDnsClient(), |
| + net::BoundNetLog(), |
| + max_concurrent_queries); |
| + } |
| + |
| + void QueryLeafIndexAsync(LogDnsClient* log_client, |
| + base::StringPiece log_domain, |
| + base::StringPiece leaf_hash, |
| + const LogDnsClient::LeafIndexCallback& callback) { |
| + log_client->QueryLeafIndex(log_domain, leaf_hash, callback); |
| + } |
| + |
| + // Convenience function for calling QueryLeafIndexAsync synchronously. |
| void QueryLeafIndex(base::StringPiece log_domain, |
| base::StringPiece leaf_hash, |
| MockLeafIndexCallback* callback) { |
| - LogDnsClient log_client(mock_dns_.CreateDnsClient(), net::BoundNetLog()); |
| - log_client.QueryLeafIndex(log_domain, leaf_hash, callback->AsCallback()); |
| + std::unique_ptr<LogDnsClient> log_client = CreateLogDnsClient(0); |
| + QueryLeafIndexAsync(log_client.get(), log_domain, leaf_hash, |
| + callback->AsCallback()); |
| callback->WaitUntilRun(); |
| } |
| + void QueryAuditProofAsync(LogDnsClient* log_client, |
| + base::StringPiece log_domain, |
| + uint64_t leaf_index, |
| + uint64_t tree_size, |
| + const LogDnsClient::AuditProofCallback& callback) { |
| + log_client->QueryAuditProof(log_domain, leaf_index, tree_size, callback); |
| + } |
| + |
| + // Convenience function for calling QueryAuditProofAsync synchronously. |
| void QueryAuditProof(base::StringPiece log_domain, |
| uint64_t leaf_index, |
| uint64_t tree_size, |
| MockAuditProofCallback* callback) { |
| - LogDnsClient log_client(mock_dns_.CreateDnsClient(), net::BoundNetLog()); |
| - log_client.QueryAuditProof(log_domain, leaf_index, tree_size, |
| - callback->AsCallback()); |
| + std::unique_ptr<LogDnsClient> log_client = CreateLogDnsClient(0); |
| + QueryAuditProofAsync(log_client.get(), log_domain, leaf_index, tree_size, |
| + callback->AsCallback()); |
| callback->WaitUntilRun(); |
| } |
| @@ -157,7 +184,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndex) { |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsOk()); |
| - EXPECT_THAT(callback.leaf_index(), 123456); |
| + EXPECT_THAT(callback.leaf_index(), Eq(123456u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsThatLogDomainDoesNotExist) { |
| @@ -169,7 +196,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsThatLogDomainDoesNotExist) { |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerFailure) { |
| @@ -181,7 +208,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerFailure) { |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerRefusal) { |
| @@ -193,7 +220,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerRefusal) { |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, |
| @@ -206,7 +233,7 @@ TEST_P(LogDnsClientTest, |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, |
| @@ -219,7 +246,7 @@ TEST_P(LogDnsClientTest, |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, |
| @@ -231,7 +258,7 @@ TEST_P(LogDnsClientTest, |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, |
| @@ -244,7 +271,7 @@ TEST_P(LogDnsClientTest, |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, |
| @@ -257,7 +284,7 @@ TEST_P(LogDnsClientTest, |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsEmpty) { |
| @@ -265,7 +292,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsEmpty) { |
| QueryLeafIndex("", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsNull) { |
| @@ -273,7 +300,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsNull) { |
| QueryLeafIndex(nullptr, kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsInvalid) { |
| @@ -281,7 +308,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsInvalid) { |
| QueryLeafIndex("ct.test", "foo", &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsEmpty) { |
| @@ -289,7 +316,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsEmpty) { |
| QueryLeafIndex("ct.test", "", &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsNull) { |
| @@ -297,7 +324,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsNull) { |
| QueryLeafIndex("ct.test", nullptr, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsSocketError) { |
| @@ -309,7 +336,7 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsSocketError) { |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryLeafIndexReportsTimeout) { |
| @@ -320,14 +347,15 @@ TEST_P(LogDnsClientTest, QueryLeafIndexReportsTimeout) { |
| QueryLeafIndex("ct.test", kLeafHash, &callback); |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); |
| - EXPECT_THAT(callback.leaf_index(), 0); |
| + EXPECT_THAT(callback.leaf_index(), Eq(0u)); |
| } |
| TEST_P(LogDnsClientTest, QueryAuditProof) { |
| const std::vector<std::string> audit_proof = GetSampleAuditProof(20); |
| - // It should require 3 queries to collect the entire audit proof, as there is |
| - // only space for 7 nodes per UDP packet. |
| + // It should require 3 requests to collect the entire audit proof, as there is |
| + // only space for 7 nodes per TXT record. One node is 32 bytes long and the |
| + // TXT RDATA can have a maximum length of 255 bytes (255 / 32). |
| mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", |
| audit_proof.begin(), |
| audit_proof.begin() + 7); |
| @@ -343,9 +371,10 @@ TEST_P(LogDnsClientTest, QueryAuditProof) { |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsOk()); |
| ASSERT_THAT(callback.proof(), NotNull()); |
| - EXPECT_THAT(callback.proof()->leaf_index, 123456); |
| - // EXPECT_THAT(callback.proof()->tree_size, 999999); |
| - EXPECT_THAT(callback.proof()->nodes, audit_proof); |
| + EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u)); |
| + // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
| + // EXPECT_THAT(callback.proof()->tree_size, Eq(999999)); |
| + EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof)); |
| } |
| TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) { |
| @@ -376,9 +405,10 @@ TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) { |
| ASSERT_TRUE(callback.called()); |
| EXPECT_THAT(callback.net_error(), IsOk()); |
| ASSERT_THAT(callback.proof(), NotNull()); |
| - EXPECT_THAT(callback.proof()->leaf_index, 123456); |
| - // EXPECT_THAT(callback.proof()->tree_size, 999999); |
| - EXPECT_THAT(callback.proof()->nodes, audit_proof); |
| + EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u)); |
| + // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
| + // EXPECT_THAT(callback.proof()->tree_size, Eq(999999)); |
| + EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof)); |
| } |
| TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) { |
| @@ -514,7 +544,7 @@ TEST_P(LogDnsClientTest, QueryAuditProofReportsTimeout) { |
| TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { |
| std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); |
| net::DnsClient* dns_client = tmp.get(); |
| - LogDnsClient log_client(std::move(tmp), net::BoundNetLog()); |
| + LogDnsClient log_client(std::move(tmp), net::BoundNetLog(), 0); |
| // Get the current DNS config, modify it and broadcast the update. |
| net::DnsConfig config(*dns_client->GetConfig()); |
| @@ -530,7 +560,7 @@ TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { |
| TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) { |
| std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); |
| net::DnsClient* dns_client = tmp.get(); |
| - LogDnsClient log_client(std::move(tmp), net::BoundNetLog()); |
| + LogDnsClient log_client(std::move(tmp), net::BoundNetLog(), 0); |
| // Get the current DNS config, modify it and broadcast the update. |
| net::DnsConfig config(*dns_client->GetConfig()); |
| @@ -543,6 +573,283 @@ TEST_P(LogDnsClientTest, IgnoresLatestDnsConfigIfInvalid) { |
| EXPECT_THAT(dns_client->GetConfig()->nameservers, Not(IsEmpty())); |
| } |
| +TEST_P(LogDnsClientTest, CanPerformLeafIndexQueriesInParallel) { |
| + // Test that 3 leaf index queries can be performed in parallel. |
| + constexpr size_t kNumOfParallelQueries = 3; |
| + std::unique_ptr<LogDnsClient> log_client = |
| + CreateLogDnsClient(kNumOfParallelQueries); |
| + MockLeafIndexCallback callbacks[kNumOfParallelQueries]; |
| + |
| + // Expect 3 requests. |
| + for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
| + mock_dns_.ExpectLeafIndexRequestAndResponse( |
| + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", |
| + "123456"); |
|
Ryan Sleevi
2016/09/16 02:11:03
Is this value necessary as part of the test? The s
Rob Percival
2016/09/16 16:28:19
They're required to test that nothing goes quietly
Ryan Sleevi
2016/09/17 01:51:52
Right, with the current structure (using the same
Rob Percival
2016/09/20 18:54:42
Done.
|
| + } |
| + |
| + // Start the queries. |
| + for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
| + QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHash, |
| + callbacks[i].AsCallback()); |
| + } |
| + |
| + // Wait for each query to complete and check its results. |
| + for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
| + MockLeafIndexCallback& callback = callbacks[i]; |
| + callback.WaitUntilRun(); |
| + |
| + SCOPED_TRACE(i); |
| + EXPECT_TRUE(callback.called()); |
| + if (callback.called()) { |
| + EXPECT_THAT(callback.net_error(), IsOk()); |
| + EXPECT_THAT(callback.leaf_index(), Eq(123456u)); |
| + } |
| + } |
|
Ryan Sleevi
2016/09/16 02:11:03
For what it's worth, I spent 20 minutes digging th
Rob Percival
2016/09/16 16:28:19
This is another thing that was only added as a res
Ryan Sleevi
2016/09/17 01:51:52
Link to previous CL?
Rob Percival
2016/09/20 18:54:42
https://codereview.chromium.org/2066553002/#ps1800
Ryan Sleevi
2016/09/22 04:37:07
Thanks. I think there was a breakdown in communica
Rob Percival
2016/09/22 11:33:23
Ah I see, TestCompletionCallback has a unique_ptr<
|
| +} |
| + |
| +TEST_P(LogDnsClientTest, CanPerformAuditProofQueriesInParallel) { |
| + // Check that 3 audit proof queries can be performed in parallel. |
| + constexpr size_t kNumOfParallelQueries = 3; |
| + std::unique_ptr<LogDnsClient> log_client = |
| + CreateLogDnsClient(kNumOfParallelQueries); |
| + MockAuditProofCallback callbacks[kNumOfParallelQueries]; |
| + const std::vector<std::string> audit_proof = GetSampleAuditProof(20); |
| + |
| + // It should require 3 requests to collect the entire audit proof, as there is |
| + // only space for 7 nodes per TXT record. One node is 32 bytes long and the |
| + // TXT RDATA can have a maximum length of 255 bytes (255 / 32). Expect each of |
| + // these queries to occur once for each call to QueryAuditProof. |
| + |
| + for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
| + mock_dns_.ExpectAuditProofRequestAndResponse( |
| + "0.123456.999999.tree.ct.test.", audit_proof.begin(), |
| + audit_proof.begin() + 7); |
| + } |
| + |
| + for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
| + mock_dns_.ExpectAuditProofRequestAndResponse( |
| + "7.123456.999999.tree.ct.test.", audit_proof.begin() + 7, |
| + audit_proof.begin() + 14); |
| + } |
| + |
| + for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
| + mock_dns_.ExpectAuditProofRequestAndResponse( |
| + "14.123456.999999.tree.ct.test.", audit_proof.begin() + 14, |
| + audit_proof.end()); |
| + } |
| + |
| + // Start the queries. |
| + for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
| + QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, |
| + callbacks[i].AsCallback()); |
| + } |
| + |
| + // Wait for each query to complete and check its results. |
| + for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
| + MockAuditProofCallback& callback = callbacks[i]; |
| + callbacks[i].WaitUntilRun(); |
| + |
| + SCOPED_TRACE(i); |
| + EXPECT_TRUE(callback.called()); |
| + if (callback.called()) { |
| + EXPECT_THAT(callback.net_error(), IsOk()); |
| + EXPECT_THAT(callback.proof(), NotNull()); |
| + if (callback.proof() != nullptr) { |
| + EXPECT_THAT(callback.proof()->leaf_index, Eq(123456u)); |
| + // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
| + // EXPECT_THAT(callback.proof()->tree_size, Eq(999999)); |
| + EXPECT_THAT(callback.proof()->nodes, Eq(audit_proof)); |
| + } |
| + } |
| + } |
| +} |
| + |
| +TEST_P(LogDnsClientTest, CanPerformLeafIndexAndAuditProofQueriesInParallel) { |
| + // Check that a leaf index and audit proof query can be performed in parallel. |
| + constexpr size_t kNumOfParallelQueries = 2; |
| + std::unique_ptr<LogDnsClient> log_client = |
| + CreateLogDnsClient(kNumOfParallelQueries); |
| + MockLeafIndexCallback leaf_index_callback; |
| + MockAuditProofCallback audit_proof_callback; |
| + const std::vector<std::string> audit_proof = GetSampleAuditProof(20); |
| + |
| + mock_dns_.ExpectLeafIndexRequestAndResponse( |
| + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", |
| + "123456"); |
| + |
| + // It should require 3 requests to collect the entire audit proof, as there is |
| + // only space for 7 nodes per TXT record. One node is 32 bytes long and the |
| + // TXT RDATA can have a maximum length of 255 bytes (255 / 32). |
| + mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", |
| + audit_proof.begin(), |
| + audit_proof.begin() + 7); |
| + mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.", |
| + audit_proof.begin() + 7, |
| + audit_proof.begin() + 14); |
| + mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.", |
| + audit_proof.begin() + 14, |
| + audit_proof.end()); |
| + |
| + // Start the queries. |
| + QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHash, |
| + leaf_index_callback.AsCallback()); |
| + QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, |
| + audit_proof_callback.AsCallback()); |
| + |
| + // Wait for the queries to complete, then check their results. |
| + leaf_index_callback.WaitUntilRun(); |
| + audit_proof_callback.WaitUntilRun(); |
| + |
| + EXPECT_TRUE(leaf_index_callback.called()); |
| + if (leaf_index_callback.called()) { |
| + EXPECT_THAT(leaf_index_callback.net_error(), IsOk()); |
| + EXPECT_THAT(leaf_index_callback.leaf_index(), Eq(123456u)); |
| + } |
| + |
| + EXPECT_TRUE(audit_proof_callback.called()); |
| + if (audit_proof_callback.called()) { |
| + EXPECT_THAT(audit_proof_callback.net_error(), IsOk()); |
| + EXPECT_THAT(audit_proof_callback.proof(), NotNull()); |
| + if (audit_proof_callback.proof() != nullptr) { |
| + EXPECT_THAT(audit_proof_callback.proof()->leaf_index, Eq(123456u)); |
| + // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
| + // EXPECT_THAT(audit_proof_callback.proof()->tree_size, Eq(999999)); |
| + EXPECT_THAT(audit_proof_callback.proof()->nodes, Eq(audit_proof)); |
| + } |
| + } |
| +} |
| + |
| +TEST_P(LogDnsClientTest, CanBeThrottledToOneLeafIndexQueryAtATime) { |
| + // Check that leaf index queries can be rate-limited to one at a time. |
| + // The second query, initiated while the first is in progress, should fail. |
| + mock_dns_.ExpectLeafIndexRequestAndResponse( |
| + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", |
| + "123456"); |
| + |
| + const size_t max_concurrent_queries = 1; |
| + std::unique_ptr<LogDnsClient> log_client = |
| + CreateLogDnsClient(max_concurrent_queries); |
| + |
| + // Start the queries. |
| + MockLeafIndexCallback callback1; |
| + QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHash, |
| + callback1.AsCallback()); |
| + MockLeafIndexCallback callback2; |
| + QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHash, |
| + callback2.AsCallback()); |
| + |
| + callback1.WaitUntilRun(); |
| + callback2.WaitUntilRun(); |
| + |
| + // Check that the first query succeeded. |
| + EXPECT_TRUE(callback1.called()); |
| + if (callback1.called()) { |
|
Ryan Sleevi
2016/09/16 02:11:03
This is non-obvious to me why you have an EXPECT_T
Rob Percival
2016/09/16 16:28:19
It's actually "Expect that this code will be calle
Ryan Sleevi
2016/09/17 01:51:52
Why?
In the face of failure, what new and additio
Rob Percival
2016/09/20 18:54:42
As discussed in https://testing.googleblog.com/200
Ryan Sleevi
2016/09/22 04:37:07
Apologies that I worded the question poorly, and p
Rob Percival
2016/09/22 11:33:23
Very well. I'm not entirely convinced, but I'll de
|
| + EXPECT_THAT(callback1.net_error(), IsOk()); |
| + EXPECT_THAT(callback1.leaf_index(), Eq(123456u)); |
| + } |
| + |
| + // Check that the second query failed. |
| + EXPECT_TRUE(callback2.called()); |
| + if (callback2.called()) { |
| + EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED)); |
| + EXPECT_THAT(callback2.leaf_index(), Eq(0u)); |
| + } |
| +} |
| + |
| +TEST_P(LogDnsClientTest, CanBeThrottledToOneAuditProofQueryAtATime) { |
| + // Check that audit proof queries can be rate-limited to one at a time. |
| + // The second query, initiated while the first is in progress, should fail. |
| + const std::vector<std::string> audit_proof = GetSampleAuditProof(20); |
| + |
| + // It should require 3 requests to collect the entire audit proof, as there is |
| + // only space for 7 nodes per TXT record. One node is 32 bytes long and the |
| + // TXT RDATA can have a maximum length of 255 bytes (255 / 32). |
| + // Rate limiting should not interfere with these requests. |
| + mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", |
| + audit_proof.begin(), |
| + audit_proof.begin() + 7); |
| + mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.", |
| + audit_proof.begin() + 7, |
| + audit_proof.begin() + 14); |
| + mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.", |
| + audit_proof.begin() + 14, |
| + audit_proof.end()); |
| + |
| + const size_t max_concurrent_queries = 1; |
| + std::unique_ptr<LogDnsClient> log_client = |
| + CreateLogDnsClient(max_concurrent_queries); |
| + |
| + // Start the queries. |
| + MockAuditProofCallback callback1; |
| + QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, |
| + callback1.AsCallback()); |
| + MockAuditProofCallback callback2; |
| + QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, |
| + callback2.AsCallback()); |
| + |
| + callback1.WaitUntilRun(); |
| + callback2.WaitUntilRun(); |
| + |
| + // Check that the first query succeeded. |
| + EXPECT_TRUE(callback1.called()); |
| + if (callback1.called()) { |
| + EXPECT_THAT(callback1.net_error(), IsOk()); |
| + EXPECT_THAT(callback1.proof(), NotNull()); |
| + if (callback1.proof() != nullptr) { |
| + EXPECT_THAT(callback1.proof()->leaf_index, Eq(123456u)); |
| + // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
| + // EXPECT_THAT(callback1.proof()->tree_size, Eq(999999)); |
| + EXPECT_THAT(callback1.proof()->nodes, Eq(audit_proof)); |
| + } |
| + } |
| + |
| + // Check that the second query failed. |
| + EXPECT_TRUE(callback2.called()); |
| + if (callback2.called()) { |
| + EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED)); |
| + EXPECT_THAT(callback2.proof(), IsNull()); |
| + } |
| +} |
| + |
| +TEST_P(LogDnsClientTest, ThrottlingAppliesAcrossQueryTypes) { |
| + // Check that queries can be rate-limited to one at a time, regardless of the |
| + // type of query. The second query, initiated while the first is in progress, |
| + // should fail. |
| + mock_dns_.ExpectLeafIndexRequestAndResponse( |
| + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", |
| + "123456"); |
| + |
| + const size_t max_concurrent_queries = 1; |
| + std::unique_ptr<LogDnsClient> log_client = |
| + CreateLogDnsClient(max_concurrent_queries); |
| + |
| + // Start the queries. |
| + MockLeafIndexCallback leaf_index_callback; |
| + QueryLeafIndexAsync(log_client.get(), "ct.test", kLeafHash, |
| + leaf_index_callback.AsCallback()); |
| + MockAuditProofCallback audit_proof_callback; |
| + QueryAuditProofAsync(log_client.get(), "ct.test", 123456, 999999, |
| + audit_proof_callback.AsCallback()); |
| + |
| + leaf_index_callback.WaitUntilRun(); |
| + audit_proof_callback.WaitUntilRun(); |
| + |
| + // Check that the first query succeeded. |
| + EXPECT_TRUE(leaf_index_callback.called()); |
| + if (leaf_index_callback.called()) { |
| + EXPECT_THAT(leaf_index_callback.net_error(), IsOk()); |
| + EXPECT_THAT(leaf_index_callback.leaf_index(), Eq(123456u)); |
| + } |
| + |
| + // Check that the second query failed. |
| + EXPECT_TRUE(audit_proof_callback.called()); |
| + if (audit_proof_callback.called()) { |
| + EXPECT_THAT(audit_proof_callback.net_error(), |
| + IsError(net::ERR_TEMPORARILY_THROTTLED)); |
| + EXPECT_THAT(audit_proof_callback.proof(), IsNull()); |
| + } |
| +} |
| + |
| INSTANTIATE_TEST_CASE_P(ReadMode, |
| LogDnsClientTest, |
| ::testing::Values(net::IoMode::ASYNC, |