| 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 aa01511448fa48c2e70d093362d9121bc3c998bf..0877f155f15e5b1efbccbe2a9895b35a55ee07f2 100644
|
| --- a/net/cert/multi_threaded_cert_verifier_unittest.cc
|
| +++ b/net/cert/multi_threaded_cert_verifier_unittest.cc
|
| @@ -379,6 +379,41 @@ TEST_F(MultiThreadedCertVerifierTest, RequestParamsComparators) {
|
| }
|
| }
|
|
|
| +TEST_F(MultiThreadedCertVerifierTest, PersistRequestParams) {
|
| + SHA1HashValue a_key;
|
| + memset(a_key.data, 'a', sizeof(a_key.data));
|
| +
|
| + const CertificateList empty_list;
|
| + CertificateList test_list;
|
| + test_list.push_back(
|
| + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"));
|
| +
|
| + // Key to test.
|
| + MultiThreadedCertVerifier::RequestParams key(a_key, a_key, "www.example.test",
|
| + std::string(), 0, test_list);
|
| +
|
| + // Restoring invalid pickled data should fail.
|
| + base::Pickle pickle;
|
| + EXPECT_TRUE(pickle.WriteString(std::string()));
|
| + base::PickleIterator corrupt_iter(pickle);
|
| + MultiThreadedCertVerifier::RequestParams key1;
|
| + EXPECT_FALSE(MultiThreadedCertVerifier::RequestParams::CreateFromPickle(
|
| + &corrupt_iter, &key1));
|
| +
|
| + // Persisting and restoring valid object should succeed.
|
| + base::Pickle pickle1;
|
| + EXPECT_TRUE(key.Persist(&pickle1));
|
| + base::PickleIterator iter(pickle1);
|
| + EXPECT_TRUE(
|
| + MultiThreadedCertVerifier::RequestParams::CreateFromPickle(&iter, &key1));
|
| +
|
| + EXPECT_EQ(key.hostname, key1.hostname);
|
| + EXPECT_EQ(key.flags, key1.flags);
|
| + EXPECT_EQ(key.hash_values.size(), key1.hash_values.size());
|
| + for (size_t i = 0; i < key.hash_values.size(); ++i)
|
| + EXPECT_TRUE(key.hash_values[i].Equals(key1.hash_values[i]));
|
| +}
|
| +
|
| TEST_F(MultiThreadedCertVerifierTest, CertTrustAnchorProvider) {
|
| MockCertTrustAnchorProvider trust_provider;
|
| verifier_.SetCertTrustAnchorProvider(&trust_provider);
|
| @@ -512,4 +547,158 @@ TEST_F(MultiThreadedCertVerifierTest, MultipleInflightJoin) {
|
| ASSERT_EQ(2u, verifier_.inflight_joins());
|
| }
|
|
|
| +TEST_F(MultiThreadedCertVerifierTest, PersistCache) {
|
| + 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;
|
| + scoped_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());
|
| +
|
| + base::Pickle pickle(sizeof(base::Pickle::Header));
|
| + EXPECT_TRUE(verifier_.SerializeCache(&pickle));
|
| +
|
| + // Clear the cache.
|
| + verifier_.ClearCache();
|
| + ASSERT_EQ(0u, verifier_.GetCacheSize());
|
| +
|
| + // Restore the cache from the pickled data.
|
| + base::PickleIterator iter(pickle);
|
| + EXPECT_TRUE(MultiThreadedCertVerifier::CreateFromPickle(&iter, &verifier_));
|
| + 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(3u, verifier_.requests());
|
| + ASSERT_EQ(2u, verifier_.cache_hits());
|
| + ASSERT_EQ(0u, verifier_.inflight_joins());
|
| + ASSERT_EQ(1u, verifier_.GetCacheSize());
|
| +}
|
| +
|
| +TEST_F(MultiThreadedCertVerifierTest, PersistCacheExpiredEntry) {
|
| + 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;
|
| + scoped_ptr<CertVerifier::Request> request;
|
| +
|
| + // Verify that there is no cache hit.
|
| + 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 and verify that there is a cache hit.
|
| + ASSERT_NE(ERR_IO_PENDING, error);
|
| + ASSERT_TRUE(IsCertificateError(error));
|
| + ASSERT_FALSE(request);
|
| + ASSERT_EQ(2u, verifier_.requests());
|
| + ASSERT_EQ(1u, verifier_.cache_hits()); // cache hit.
|
| + ASSERT_EQ(0u, verifier_.inflight_joins());
|
| + ASSERT_EQ(1u, verifier_.GetCacheSize());
|
| +
|
| + // Test cache expiration, by adding expired data.
|
| + const CertificateList empty_cert_list;
|
| + const CertificateList& additional_trust_anchors =
|
| + verifier_.trust_anchor_provider_
|
| + ? verifier_.trust_anchor_provider_->GetAdditionalTrustAnchors()
|
| + : empty_cert_list;
|
| + const MultiThreadedCertVerifier::RequestParams key(
|
| + test_cert->fingerprint(), test_cert->ca_fingerprint(), example_hostname,
|
| + ocsp_response, flags, additional_trust_anchors);
|
| + const MultiThreadedCertVerifier::CertVerifierCache::value_type* cached_entry =
|
| + verifier_.cache_.Get(key, MultiThreadedCertVerifier::CacheValidityPeriod(
|
| + base::Time::Now()));
|
| + // TODO(rtenneti): use |kTTLSecs| instead of hardcoded 1800ms.
|
| + base::Time start_time =
|
| + base::Time::Now() - base::TimeDelta::FromSeconds(3600);
|
| + verifier_.cache_.Put(
|
| + key, *cached_entry,
|
| + MultiThreadedCertVerifier::CacheValidityPeriod(start_time),
|
| + MultiThreadedCertVerifier::CacheValidityPeriod(
|
| + start_time, start_time + base::TimeDelta::FromSeconds(1800)));
|
| +
|
| + // Persist the data.
|
| + base::Pickle pickle(sizeof(base::Pickle::Header));
|
| + EXPECT_TRUE(verifier_.SerializeCache(&pickle));
|
| +
|
| + // Clear the cache.
|
| + verifier_.ClearCache();
|
| + ASSERT_EQ(0u, verifier_.GetCacheSize());
|
| +
|
| + // Restore the persisted data.
|
| + base::PickleIterator iter(pickle);
|
| + EXPECT_TRUE(MultiThreadedCertVerifier::CreateFromPickle(&iter, &verifier_));
|
| + ASSERT_EQ(1u, verifier_.GetCacheSize());
|
| +
|
| + 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);
|
| + // Verify the entry is evicted from the cache.
|
| + ASSERT_EQ(0u, verifier_.GetCacheSize());
|
| + ASSERT_TRUE(request);
|
| + error = callback.WaitForResult();
|
| + ASSERT_TRUE(IsCertificateError(error));
|
| + ASSERT_EQ(3u, verifier_.requests());
|
| + // Verify number of cache hits hasn't increased.
|
| + ASSERT_EQ(1u, verifier_.cache_hits());
|
| + ASSERT_EQ(0u, verifier_.inflight_joins());
|
| + ASSERT_EQ(1u, verifier_.GetCacheSize());
|
| +}
|
| +
|
| } // namespace net
|
|
|