Chromium Code Reviews| 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 |