Index: net/cert/multi_threaded_cert_verifier_unittest.cc |
diff --git a/net/cert/multi_threaded_cert_verifier_unittest.cc b/net/cert/multi_threaded_cert_verifier_unittest.cc |
index 0704a13c3235e961c1750f9bc879ed7e6c7ba375..0d8bd3a3c6193804e9fa7d841e910771c555efe0 100644 |
--- a/net/cert/multi_threaded_cert_verifier_unittest.cc |
+++ b/net/cert/multi_threaded_cert_verifier_unittest.cc |
@@ -67,6 +67,20 @@ class MockCertTrustAnchorProvider : public CertTrustAnchorProvider { |
MOCK_METHOD0(GetAdditionalTrustAnchors, const CertificateList&()); |
}; |
+bool HashValueVectorEqual(const HashValueVector& a, const HashValueVector& b) { |
+ size_t size = a.size(); |
+ |
+ if (size != b.size()) |
+ return false; |
+ |
+ for (size_t i = 0; i < size; ++i) { |
Ryan Sleevi
2016/05/13 20:18:13
alternative: return std::equal(a.begin(), a.end(),
|
+ if (!a[i].Equals(b[i])) |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
} // namespace |
class MultiThreadedCertVerifierTest : public ::testing::Test { |
@@ -514,4 +528,200 @@ TEST_F(MultiThreadedCertVerifierTest, MultipleInflightJoin) { |
ASSERT_EQ(2u, verifier_.inflight_joins()); |
} |
+TEST_F(MultiThreadedCertVerifierTest, CacheHitIterator) { |
+ base::FilePath certs_dir = GetTestCertsDirectory(); |
+ scoped_refptr<X509Certificate> test_cert( |
+ ImportCertFromFile(certs_dir, "ok_cert.pem")); |
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get()); |
+ |
+ std::string example_hostname("www.example.com"); |
+ std::string ocsp_response; |
+ int flags = 0; |
+ base::Time start_time = base::Time::Now(); |
+ int error; |
+ CertVerifyResult verify_result; |
+ TestCompletionCallback callback; |
+ std::unique_ptr<CertVerifier::Request> request; |
+ |
+ error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
+ flags, NULL, &verify_result, callback.callback(), |
+ &request, BoundNetLog()); |
+ ASSERT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request); |
+ error = callback.WaitForResult(); |
+ ASSERT_TRUE(IsCertificateError(error)); |
+ ASSERT_EQ(1u, verifier_.requests()); |
+ ASSERT_EQ(0u, verifier_.cache_hits()); |
+ ASSERT_EQ(0u, verifier_.inflight_joins()); |
+ ASSERT_EQ(1u, verifier_.GetCacheSize()); |
+ |
+ // Verify Iterator returns the correct data. |
+ base::Time curr_time = base::Time::Now(); |
+ MultiThreadedCertVerifier::Iterator iterator(verifier_); |
+ EXPECT_TRUE(iterator.HasNext()); |
+ ASSERT_EQ(example_hostname, iterator.hostname()); |
+ ASSERT_EQ(flags, iterator.flags()); |
+ ASSERT_LE(start_time, iterator.start_time()); |
+ ASSERT_GE(curr_time, iterator.start_time()); |
+ ASSERT_EQ(error, iterator.error()); |
+ const CertVerifyResult& result = iterator.result(); |
+ ASSERT_EQ(verify_result.cert_status, result.cert_status); |
+ ASSERT_EQ(verify_result.has_md2, result.has_md2); |
+ ASSERT_EQ(verify_result.has_md4, result.has_md4); |
+ ASSERT_EQ(verify_result.has_md5, result.has_md5); |
+ ASSERT_EQ(verify_result.has_sha1, result.has_sha1); |
+ ASSERT_EQ(verify_result.has_sha1_leaf, result.has_sha1_leaf); |
+ ASSERT_EQ(verify_result.is_issued_by_known_root, |
+ result.is_issued_by_known_root); |
+ ASSERT_EQ(verify_result.is_issued_by_additional_trust_anchor, |
+ result.is_issued_by_additional_trust_anchor); |
+ ASSERT_EQ(verify_result.has_md2, result.has_md2); |
+ ASSERT_EQ(verify_result.common_name_fallback_used, |
+ result.common_name_fallback_used); |
+ EXPECT_TRUE(HashValueVectorEqual(verify_result.public_key_hashes, |
+ result.public_key_hashes)); |
+ EXPECT_TRUE( |
+ verify_result.verified_cert.get()->Equals(result.verified_cert.get())); |
+ |
+ ASSERT_LE(start_time, iterator.verification_time()); |
+ ASSERT_GE(curr_time, iterator.verification_time()); |
+ |
+ // TODO(rtenneti): use |kTTLSecs| instead of hardcoded 1800ms. |
+ base::Time expected_expiration_time = |
+ curr_time + base::TimeDelta::FromSeconds(3600); |
+ ASSERT_LE(start_time, iterator.expiration_time()); |
+ ASSERT_GE(expected_expiration_time, iterator.expiration_time()); |
+ |
+ iterator.Advance(); |
+ EXPECT_FALSE(iterator.HasNext()); |
+} |
+ |
+TEST_F(MultiThreadedCertVerifierTest, AddCertResult) { |
+ base::FilePath certs_dir = GetTestCertsDirectory(); |
+ scoped_refptr<X509Certificate> test_cert( |
+ ImportCertFromFile(certs_dir, "ok_cert.pem")); |
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get()); |
+ |
+ std::string example_hostname("www.example.com"); |
+ std::string ocsp_response; |
+ int flags = 0; |
+ CRLSet* crl_set = NULL; |
+ int error; |
+ CertVerifyResult verify_result; |
+ TestCompletionCallback callback; |
+ std::unique_ptr<CertVerifier::Request> request; |
+ |
+ error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
+ flags, crl_set, &verify_result, callback.callback(), |
+ &request, BoundNetLog()); |
+ ASSERT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request); |
+ error = callback.WaitForResult(); |
+ ASSERT_TRUE(IsCertificateError(error)); |
+ ASSERT_EQ(1u, verifier_.requests()); |
+ ASSERT_EQ(0u, verifier_.cache_hits()); |
+ ASSERT_EQ(0u, verifier_.inflight_joins()); |
+ ASSERT_EQ(1u, verifier_.GetCacheSize()); |
+ |
+ error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
+ flags, crl_set, &verify_result, callback.callback(), |
+ &request, BoundNetLog()); |
+ // Synchronous completion. |
+ ASSERT_NE(ERR_IO_PENDING, error); |
+ ASSERT_TRUE(IsCertificateError(error)); |
+ ASSERT_FALSE(request); |
+ ASSERT_EQ(2u, verifier_.requests()); |
+ ASSERT_EQ(1u, verifier_.cache_hits()); |
+ ASSERT_EQ(0u, verifier_.inflight_joins()); |
+ ASSERT_EQ(1u, verifier_.GetCacheSize()); |
+ |
+ MultiThreadedCertVerifier::Iterator iterator(verifier_); |
+ EXPECT_TRUE(iterator.HasNext()); |
+ ASSERT_EQ(example_hostname, iterator.hostname()); |
+ |
+ std::vector<SHA1HashValue> dummp_hash_values; |
+ // Invalid hostname. |
Ryan Sleevi
2016/05/13 20:18:13
Separate
|
+ bool cert_result = verifier_.AddCertResult( |
+ std::string(), iterator.flags(), iterator.hash_values(), |
+ iterator.start_time(), iterator.error(), iterator.result(), |
+ iterator.verification_time(), iterator.expiration_time()); |
+ EXPECT_FALSE(cert_result); |
+ // Invalid hash_values. |
Ryan Sleevi
2016/05/13 20:18:13
Separate
|
+ cert_result = verifier_.AddCertResult( |
+ iterator.hostname(), iterator.flags(), dummp_hash_values, |
+ iterator.start_time(), iterator.error(), iterator.result(), |
+ iterator.verification_time(), iterator.expiration_time()); |
+ EXPECT_FALSE(cert_result); |
+ // Invalid start_time. |
Ryan Sleevi
2016/05/13 20:18:13
Separate
|
+ cert_result = verifier_.AddCertResult( |
+ iterator.hostname(), iterator.flags(), iterator.hash_values(), |
+ base::Time::Now(), iterator.error(), iterator.result(), |
+ iterator.verification_time(), iterator.expiration_time()); |
+ EXPECT_FALSE(cert_result); |
+ // Corrupted start_time. |
Ryan Sleevi
2016/05/13 20:18:13
Separate
|
+ cert_result = verifier_.AddCertResult( |
+ iterator.hostname(), iterator.flags(), iterator.hash_values(), |
+ iterator.start_time() + base::TimeDelta::FromSeconds(1), iterator.error(), |
+ iterator.result(), iterator.verification_time(), |
+ iterator.expiration_time()); |
+ EXPECT_FALSE(cert_result); |
+ // Corrupted verification_time. |
Ryan Sleevi
2016/05/13 20:18:13
Separate
|
+ cert_result = verifier_.AddCertResult( |
+ iterator.hostname(), iterator.flags(), iterator.hash_values(), |
+ iterator.start_time(), iterator.error(), iterator.result(), |
+ iterator.verification_time() + base::TimeDelta::FromSeconds(10), |
+ iterator.expiration_time()); |
+ EXPECT_FALSE(cert_result); |
+ // Corrupted expired entry. |
Ryan Sleevi
2016/05/13 20:18:13
Separate
|
+ cert_result = verifier_.AddCertResult( |
+ iterator.hostname(), iterator.flags(), iterator.hash_values(), |
+ iterator.start_time(), iterator.error(), iterator.result(), |
+ iterator.verification_time(), |
+ iterator.expiration_time() - base::TimeDelta::FromSeconds(10)); |
+ EXPECT_FALSE(cert_result); |
+ // Expired entry. |
Ryan Sleevi
2016/05/13 20:18:13
Separate
|
+ cert_result = verifier_.AddCertResult( |
+ iterator.hostname(), iterator.flags(), iterator.hash_values(), |
+ iterator.start_time(), iterator.error(), iterator.result(), |
+ iterator.verification_time(), base::Time::Now()); |
+ EXPECT_FALSE(cert_result); |
+ // Adding a duplicate entry. |
Ryan Sleevi
2016/05/13 20:18:13
Separate
|
+ cert_result = verifier_.AddCertResult( |
+ iterator.hostname(), iterator.flags(), iterator.hash_values(), |
+ iterator.start_time(), iterator.error(), iterator.result(), |
+ iterator.verification_time(), iterator.expiration_time()); |
+ EXPECT_FALSE(cert_result); |
+ |
+ // Save the data before clearing the cache. |
Ryan Sleevi
2016/05/13 20:18:13
Separate
|
+ std::string hostname = iterator.hostname(); |
+ flags = iterator.flags(); |
+ std::vector<SHA1HashValue> hash_values = iterator.hash_values(); |
+ base::Time start_time = iterator.start_time(); |
+ error = iterator.error(); |
+ CertVerifyResult result = iterator.result(); |
+ base::Time verification_time = iterator.verification_time(); |
+ base::Time expiration_time = iterator.expiration_time(); |
+ |
+ verifier_.ClearCache(); |
+ ASSERT_EQ(0u, verifier_.GetCacheSize()); |
+ |
+ cert_result = |
+ verifier_.AddCertResult(hostname, flags, hash_values, start_time, error, |
+ result, verification_time, expiration_time); |
+ EXPECT_TRUE(cert_result); |
+ ASSERT_EQ(1u, verifier_.GetCacheSize()); |
+ |
+ error = verifier_.Verify(test_cert.get(), example_hostname, ocsp_response, |
+ flags, crl_set, &verify_result, callback.callback(), |
+ &request, BoundNetLog()); |
+ // Synchronous completion and verify that there is a cache hit. |
+ ASSERT_NE(ERR_IO_PENDING, error); |
+ ASSERT_TRUE(IsCertificateError(error)); |
+ ASSERT_FALSE(request); |
+ ASSERT_EQ(3u, verifier_.requests()); |
+ ASSERT_EQ(2u, verifier_.cache_hits()); |
+ ASSERT_EQ(0u, verifier_.inflight_joins()); |
+ ASSERT_EQ(1u, verifier_.GetCacheSize()); |
+} |
+ |
} // namespace net |