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 3aaa72dd1667fafbad5aa4d8f5daee99acd9c97c..00782bb5e72bb99dbe567d0243a1a55d6b3a35b7 100644 |
--- a/components/certificate_transparency/log_dns_client_unittest.cc |
+++ b/components/certificate_transparency/log_dns_client_unittest.cc |
@@ -14,18 +14,20 @@ |
#include "base/memory/ptr_util.h" |
#include "base/message_loop/message_loop.h" |
#include "base/run_loop.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/stringprintf.h" |
+#include "base/test/test_timeouts.h" |
#include "components/certificate_transparency/mock_log_dns_traffic.h" |
#include "crypto/sha2.h" |
#include "net/base/net_errors.h" |
#include "net/cert/merkle_audit_proof.h" |
#include "net/cert/signed_certificate_timestamp.h" |
#include "net/dns/dns_client.h" |
#include "net/dns/dns_config_service.h" |
#include "net/dns/dns_protocol.h" |
+#include "net/log/net_log.h" |
#include "net/test/gtest_util.h" |
#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace certificate_transparency { |
@@ -68,10 +70,13 @@ const uint64_t kTreeSizes[] = {100, 10000, 1000000}; |
// is a SHA-256 hash (32 bytes), i.e. (255 / 32) == 7. |
// This means audit proofs consisting of more than 7 nodes require multiple DNS |
// requests to retrieve. |
const size_t kMaxProofNodesPerDnsResponse = 7; |
+// Returns an example Merkle audit proof containing |length| nodes. |
+// The proof cannot be used for cryptographic purposes; it is merely a |
+// placeholder. |
std::vector<std::string> GetSampleAuditProof(size_t length) { |
std::vector<std::string> audit_proof(length); |
// Makes each node of the audit proof different, so that tests are able to |
// confirm that the audit proof is reconstructed in the correct order. |
for (size_t i = 0; i < length; ++i) { |
@@ -84,37 +89,64 @@ std::vector<std::string> GetSampleAuditProof(size_t length) { |
} |
return audit_proof; |
} |
+// MockAuditProofCallback can be used as an AuditProofCallback. |
+// It will record the arguments it is invoked with and provides a helpful |
+// method for pumping the message loop until it is invoked. |
class MockAuditProofCallback { |
public: |
MockAuditProofCallback() : called_(false) {} |
bool called() const { return called_; } |
- int net_error() const { return net_error_; } |
+ net::Error result() const { return result_; } |
const net::ct::MerkleAuditProof* proof() const { return proof_.get(); } |
- void Run(int net_error, std::unique_ptr<net::ct::MerkleAuditProof> proof) { |
- EXPECT_FALSE(called_); |
- called_ = true; |
- net_error_ = net_error; |
- proof_ = std::move(proof); |
- run_loop_.Quit(); |
- } |
- |
+ // Get this callback as an AuditProofCallback. |
LogDnsClient::AuditProofCallback AsCallback() { |
return base::Bind(&MockAuditProofCallback::Run, base::Unretained(this)); |
} |
- void WaitUntilRun() { run_loop_.Run(); } |
+ // Wait until either the callback is invoked or the message loop goes idle |
+ // (after a specified |timeout|). Returns immediately if the callback has |
+ // already been invoked. |
+ void WaitUntilRun(base::TimeDelta timeout) { |
+ if (called_) { |
+ return; |
+ } |
+ |
+ // Pump the message loop until the the callback is invoked, which quits the |
+ // RunLoop, or a timeout expires and the message loop goes idle. |
+ run_loop_.reset(new base::RunLoop()); |
+ base::Closure quit_closure = run_loop_->QuitWhenIdleClosure(); |
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, |
+ quit_closure, timeout); |
+ run_loop_->Run(); |
+ run_loop_.reset(); |
+ } |
private: |
+ void Run(net::Error result, |
+ std::unique_ptr<net::ct::MerkleAuditProof> proof) { |
+ EXPECT_FALSE(called_); |
+ called_ = true; |
+ result_ = result; |
+ proof_ = std::move(proof); |
+ if (run_loop_) { |
+ run_loop_->Quit(); |
+ } |
+ } |
+ |
+ // True if the callback has been invoked. |
bool called_; |
- int net_error_; |
+ // The arguments that the callback was invoked with. |
+ net::Error result_; |
std::unique_ptr<net::ct::MerkleAuditProof> proof_; |
- base::RunLoop run_loop_; |
+ // The RunLoop currently being used to pump the message loop, as a means to |
+ // execute this callback. |
+ std::unique_ptr<base::RunLoop> run_loop_; |
}; |
class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { |
protected: |
LogDnsClientTest() |
@@ -128,27 +160,29 @@ class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { |
return base::MakeUnique<LogDnsClient>(mock_dns_.CreateDnsClient(), |
net::NetLogWithSource(), |
max_concurrent_queries); |
} |
- void QueryAuditProofAsync(LogDnsClient* log_client, |
- const std::string& log_domain, |
- const char leaf_hash[crypto::kSHA256Length], |
- uint64_t tree_size, |
- const LogDnsClient::AuditProofCallback& callback) { |
- log_client->QueryAuditProof(log_domain, leaf_hash, tree_size, callback); |
- } |
- |
- // Convenience function for calling QueryAuditProofAsync synchronously. |
- void QueryAuditProof(const std::string& log_domain, |
- const char leaf_hash[crypto::kSHA256Length], |
- uint64_t tree_size, |
- MockAuditProofCallback* callback) { |
+ // Convenience function for calling QueryAuditProof synchronously. |
+ net::Error QueryAuditProof(const std::string& log_domain, |
+ const char leaf_hash[crypto::kSHA256Length], |
+ uint64_t tree_size, |
+ MockAuditProofCallback* callback) { |
std::unique_ptr<LogDnsClient> log_client = CreateLogDnsClient(0); |
- QueryAuditProofAsync(log_client.get(), log_domain, leaf_hash, tree_size, |
- callback->AsCallback()); |
- callback->WaitUntilRun(); |
+ net::Error result = log_client->QueryAuditProof( |
+ log_domain, leaf_hash, tree_size, callback->AsCallback()); |
+ |
+ if (result == net::ERR_IO_PENDING) { |
+ callback->WaitUntilRun(TestTimeouts::action_max_timeout()); |
+ } else { |
+ // The callback isn't expected to be invoked, but pump the message loop |
+ // anyway to confirm that it indeed isn't run. Give up as soon as the |
+ // message loop is empty (zero timeout). |
+ callback->WaitUntilRun(base::TimeDelta()); |
+ } |
+ |
+ return result; |
} |
// This will be the NetworkChangeNotifier singleton for the duration of the |
// test. It is accessed statically by LogDnsClient. |
std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; |
@@ -162,170 +196,192 @@ class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { |
TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) { |
mock_dns_.ExpectRequestAndErrorResponse(kLeafIndexQnames[0], |
net::dns_protocol::kRcodeNXDOMAIN); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_NAME_NOT_RESOLVED)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsServerFailuresDuringLeafIndexRequests) { |
mock_dns_.ExpectRequestAndErrorResponse(kLeafIndexQnames[0], |
net::dns_protocol::kRcodeSERVFAIL); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_SERVER_FAILED)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsServerRefusalsDuringLeafIndexRequests) { |
mock_dns_.ExpectRequestAndErrorResponse(kLeafIndexQnames[0], |
net::dns_protocol::kRcodeREFUSED); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_SERVER_FAILED)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsMalformedResponseIfLeafIndexResponseContainsNoStrings) { |
mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], |
std::vector<base::StringPiece>()); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsMalformedResponseIfLeafIndexResponseContainsMoreThanOneString) { |
mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"123456", "7"}); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsMalformedResponseIfLeafIndexIsNotNumeric) { |
mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"foo"}); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsMalformedResponseIfLeafIndexIsFloatingPoint) { |
mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"123456.0"}); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsMalformedResponseIfLeafIndexIsEmpty) { |
mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {""}); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsMalformedResponseIfLeafIndexHasNonNumericPrefix) { |
mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"foo123456"}); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsMalformedResponseIfLeafIndexHasNonNumericSuffix) { |
mock_dns_.ExpectRequestAndResponse(kLeafIndexQnames[0], {"123456foo"}); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsEmpty) { |
MockAuditProofCallback callback; |
- QueryAuditProof("", kLeafHashes[0], kTreeSizes[0], &callback); |
- ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
- EXPECT_THAT(callback.proof(), IsNull()); |
+ ASSERT_THAT(QueryAuditProof("", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_INVALID_ARGUMENT)); |
+ ASSERT_FALSE(callback.called()); |
} |
TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsInvalid) { |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", "foo", kTreeSizes[0], &callback); |
- ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
- EXPECT_THAT(callback.proof(), IsNull()); |
+ ASSERT_THAT(QueryAuditProof("ct.test", "foo", kTreeSizes[0], &callback), |
+ IsError(net::ERR_INVALID_ARGUMENT)); |
+ ASSERT_FALSE(callback.called()); |
} |
TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsEmpty) { |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", "", kTreeSizes[0], &callback); |
- ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
- EXPECT_THAT(callback.proof(), IsNull()); |
+ ASSERT_THAT(QueryAuditProof("ct.test", "", kTreeSizes[0], &callback), |
+ IsError(net::ERR_INVALID_ARGUMENT)); |
+ ASSERT_FALSE(callback.called()); |
} |
TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLeafHashIsNull) { |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", nullptr, kTreeSizes[0], &callback); |
- ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
- EXPECT_THAT(callback.proof(), IsNull()); |
+ ASSERT_THAT(QueryAuditProof("ct.test", nullptr, kTreeSizes[0], &callback), |
+ IsError(net::ERR_INVALID_ARGUMENT)); |
+ ASSERT_FALSE(callback.called()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsSocketErrorsDuringLeafIndexRequests) { |
mock_dns_.ExpectRequestAndSocketError(kLeafIndexQnames[0], |
net::ERR_CONNECTION_REFUSED); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_CONNECTION_REFUSED)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsTimeoutsDuringLeafIndexRequests) { |
mock_dns_.ExpectRequestAndTimeout(kLeafIndexQnames[0]); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback); |
+ ASSERT_THAT( |
+ QueryAuditProof("ct.test", kLeafHashes[0], kTreeSizes[0], &callback), |
+ IsError(net::ERR_IO_PENDING)); |
+ |
+ callback.WaitUntilRun(TestTimeouts::action_max_timeout()); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_TIMED_OUT)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, QueryAuditProof) { |
const std::vector<std::string> audit_proof = GetSampleAuditProof(20); |
@@ -344,13 +400,14 @@ TEST_P(LogDnsClientTest, QueryAuditProof) { |
base::StringPrintf("%zu.123456.999999.tree.ct.test.", nodes_begin), |
audit_proof.begin() + nodes_begin, audit_proof.begin() + nodes_end); |
} |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsOk()); |
+ EXPECT_THAT(callback.result(), IsOk()); |
ASSERT_THAT(callback.proof(), NotNull()); |
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)); |
@@ -381,13 +438,14 @@ TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) { |
mock_dns_.ExpectAuditProofRequestAndResponse("13.123456.999999.tree.ct.test.", |
audit_proof.begin() + 13, |
audit_proof.end()); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsOk()); |
+ EXPECT_THAT(callback.result(), IsOk()); |
ASSERT_THAT(callback.proof(), NotNull()); |
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)); |
@@ -398,39 +456,42 @@ TEST_P(LogDnsClientTest, |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", |
net::dns_protocol::kRcodeNXDOMAIN); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_NAME_NOT_RESOLVED)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
- QueryAuditProofReportsServerFailureDuringAuditProofRequests) { |
+ QueryAuditProofReportsServerFailuresDuringAuditProofRequests) { |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", |
net::dns_protocol::kRcodeSERVFAIL); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_SERVER_FAILED)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
- QueryAuditProofReportsServerRefusalDuringAuditProofRequests) { |
+ QueryAuditProofReportsServerRefusalsDuringAuditProofRequests) { |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
mock_dns_.ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", |
net::dns_protocol::kRcodeREFUSED); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_SERVER_FAILED)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsResponseMalformedIfProofNodesResponseContainsNoStrings) { |
@@ -439,13 +500,14 @@ TEST_P(LogDnsClientTest, |
mock_dns_.ExpectRequestAndResponse("0.123456.999999.tree.ct.test.", |
std::vector<base::StringPiece>()); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsResponseMalformedIfProofNodesResponseContainsMoreThanOneString) { |
@@ -464,13 +526,14 @@ TEST_P(LogDnsClientTest, |
mock_dns_.ExpectRequestAndResponse( |
"0.123456.999999.tree.ct.test.", |
{first_chunk_of_proof, second_chunk_of_proof}); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsResponseMalformedIfNodeTooShort) { |
@@ -480,13 +543,14 @@ TEST_P(LogDnsClientTest, |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
mock_dns_.ExpectAuditProofRequestAndResponse( |
"0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end()); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfNodeTooLong) { |
// node is longer than a SHA-256 hash (33 vs 32 bytes) |
@@ -495,13 +559,14 @@ TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfNodeTooLong) { |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
mock_dns_.ExpectAuditProofRequestAndResponse( |
"0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end()); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfEmpty) { |
const std::vector<std::string> audit_proof; |
@@ -509,60 +574,67 @@ TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfEmpty) { |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
mock_dns_.ExpectAuditProofRequestAndResponse( |
"0.123456.999999.tree.ct.test.", audit_proof.begin(), audit_proof.end()); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsInvalidArgIfLeafIndexEqualToTreeSize) { |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 123456, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 123456, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_INVALID_ARGUMENT)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsInvalidArgIfLeafIndexGreaterThanTreeSize) { |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 999999); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 123456, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 123456, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_INVALID_ARGUMENT)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsSocketErrorsDuringAuditProofRequests) { |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
mock_dns_.ExpectRequestAndSocketError("0.123456.999999.tree.ct.test.", |
net::ERR_CONNECTION_REFUSED); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_CONNECTION_REFUSED)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, |
QueryAuditProofReportsTimeoutsDuringAuditProofRequests) { |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], 123456); |
mock_dns_.ExpectRequestAndTimeout("0.123456.999999.tree.ct.test."); |
MockAuditProofCallback callback; |
- QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback); |
+ ASSERT_THAT(QueryAuditProof("ct.test", kLeafHashes[0], 999999, &callback), |
+ IsError(net::ERR_IO_PENDING)); |
+ |
+ callback.WaitUntilRun(TestTimeouts::action_max_timeout()); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); |
+ EXPECT_THAT(callback.result(), IsError(net::ERR_DNS_TIMED_OUT)); |
EXPECT_THAT(callback.proof(), IsNull()); |
} |
TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigIfValid) { |
std::unique_ptr<net::DnsClient> tmp = mock_dns_.CreateDnsClient(); |
@@ -620,25 +692,26 @@ TEST_P(LogDnsClientTest, AdoptsLatestDnsConfigMidQuery) { |
net::DnsClient* dns_client = tmp.get(); |
LogDnsClient log_client(std::move(tmp), net::NetLogWithSource(), 0); |
// Start query. |
MockAuditProofCallback callback; |
- QueryAuditProofAsync(&log_client, "ct.test", kLeafHashes[0], 999999, |
- callback.AsCallback()); |
+ ASSERT_THAT(log_client.QueryAuditProof("ct.test", kLeafHashes[0], 999999, |
+ callback.AsCallback()), |
+ IsError(net::ERR_IO_PENDING)); |
// Get the current DNS config, modify it and broadcast the update. |
net::DnsConfig config(*dns_client->GetConfig()); |
ASSERT_NE(123, config.attempts); |
config.attempts = 123; |
mock_dns_.SetDnsConfig(config); |
- callback.WaitUntilRun(); |
+ callback.WaitUntilRun(TestTimeouts::action_max_timeout()); |
// Check that the DNS changes propogated before the query completed. |
EXPECT_EQ(123, dns_client->GetConfig()->attempts); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsOk()); |
+ EXPECT_THAT(callback.result(), IsOk()); |
ASSERT_THAT(callback.proof(), NotNull()); |
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)); |
@@ -702,22 +775,25 @@ TEST_P(LogDnsClientTest, CanPerformQueriesInParallel) { |
} |
} |
// Start the queries. |
for (size_t i = 0; i < kNumOfParallelQueries; ++i) { |
- QueryAuditProofAsync(log_client.get(), "ct.test", kLeafHashes[i], |
- kTreeSizes[i], callbacks[i].AsCallback()); |
+ ASSERT_THAT( |
+ log_client->QueryAuditProof("ct.test", kLeafHashes[i], kTreeSizes[i], |
+ callbacks[i].AsCallback()), |
+ IsError(net::ERR_IO_PENDING)) |
+ << "query #" << i; |
} |
// 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(); |
+ callbacks[i].WaitUntilRun(TestTimeouts::action_max_timeout()); |
SCOPED_TRACE(testing::Message() << "callbacks[" << i << "]"); |
ASSERT_TRUE(callback.called()); |
- EXPECT_THAT(callback.net_error(), IsOk()); |
+ EXPECT_THAT(callback.result(), IsOk()); |
ASSERT_THAT(callback.proof(), NotNull()); |
EXPECT_THAT(callback.proof()->leaf_index, Eq(kLeafIndices[i])); |
// TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
// EXPECT_THAT(callback.proof()->tree_size, kTreeSizes[i]); |
EXPECT_THAT(callback.proof()->nodes, Eq(audit_proofs[i])); |
@@ -749,34 +825,36 @@ TEST_P(LogDnsClientTest, CanBeThrottledToOneQueryAtATime) { |
const size_t kMaxConcurrentQueries = 1; |
std::unique_ptr<LogDnsClient> log_client = |
CreateLogDnsClient(kMaxConcurrentQueries); |
- // Start the queries. |
+ // Try to start the queries. |
MockAuditProofCallback callback1; |
- QueryAuditProofAsync(log_client.get(), "ct.test", kLeafHashes[0], 999999, |
- callback1.AsCallback()); |
+ ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], 999999, |
+ callback1.AsCallback()), |
+ IsError(net::ERR_IO_PENDING)); |
+ |
MockAuditProofCallback callback2; |
- QueryAuditProofAsync(log_client.get(), "ct.test", kLeafHashes[1], 999999, |
- callback2.AsCallback()); |
- |
- callback1.WaitUntilRun(); |
- callback2.WaitUntilRun(); |
+ ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[1], 999999, |
+ callback2.AsCallback()), |
+ IsError(net::ERR_TEMPORARILY_THROTTLED)); |
// Check that the first query succeeded. |
+ callback1.WaitUntilRun(TestTimeouts::action_max_timeout()); |
ASSERT_TRUE(callback1.called()); |
- EXPECT_THAT(callback1.net_error(), IsOk()); |
+ EXPECT_THAT(callback1.result(), IsOk()); |
ASSERT_THAT(callback1.proof(), NotNull()); |
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. |
- ASSERT_TRUE(callback2.called()); |
- EXPECT_THAT(callback2.net_error(), IsError(net::ERR_TEMPORARILY_THROTTLED)); |
- EXPECT_THAT(callback2.proof(), IsNull()); |
+ // This callback isn't expected to be invoked, but pump the message loop |
+ // anyway to confirm that it indeed isn't run. Give up as soon as the |
+ // message loop is empty (zero timeout). |
+ callback2.WaitUntilRun(base::TimeDelta()); |
+ ASSERT_FALSE(callback2.called()); |
// Try a third query, which should succeed now that the first is finished. |
mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[2], 666); |
mock_dns_.ExpectAuditProofRequestAndResponse("0.666.999999.tree.ct.test.", |
audit_proof.begin(), |
@@ -787,18 +865,18 @@ TEST_P(LogDnsClientTest, CanBeThrottledToOneQueryAtATime) { |
mock_dns_.ExpectAuditProofRequestAndResponse("14.666.999999.tree.ct.test.", |
audit_proof.begin() + 14, |
audit_proof.end()); |
MockAuditProofCallback callback3; |
- QueryAuditProofAsync(log_client.get(), "ct.test", kLeafHashes[2], 999999, |
- callback3.AsCallback()); |
- |
- callback3.WaitUntilRun(); |
+ ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[2], 999999, |
+ callback3.AsCallback()), |
+ IsError(net::ERR_IO_PENDING)); |
// Check that the third query succeeded. |
+ callback3.WaitUntilRun(TestTimeouts::action_max_timeout()); |
ASSERT_TRUE(callback3.called()); |
- EXPECT_THAT(callback3.net_error(), IsOk()); |
+ EXPECT_THAT(callback3.result(), IsOk()); |
ASSERT_THAT(callback3.proof(), NotNull()); |
EXPECT_THAT(callback3.proof()->leaf_index, Eq(666u)); |
// TODO(robpercival): Enable this once MerkleAuditProof has tree_size. |
// EXPECT_THAT(callback3.proof()->tree_size, Eq(999999)); |
EXPECT_THAT(callback3.proof()->nodes, Eq(audit_proof)); |