diff options
author | wtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-16 17:27:15 +0000 |
---|---|---|
committer | wtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-16 17:27:15 +0000 |
commit | 822581d32a6836feae73b96a2ce494a058004423 (patch) | |
tree | 925796acd3c3aeaa357378c096c5d9efec31bf36 /net/base/cert_verifier_unittest.cc | |
parent | ae89b8d559bfa6b3a2c1d404b21386bcc8995472 (diff) | |
download | chromium_src-822581d32a6836feae73b96a2ce494a058004423.zip chromium_src-822581d32a6836feae73b96a2ce494a058004423.tar.gz chromium_src-822581d32a6836feae73b96a2ce494a058004423.tar.bz2 |
Cache certificate verification results in memory.
R=agl
BUG=63357
TEST=none
Review URL: http://codereview.chromium.org/5386001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69414 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/cert_verifier_unittest.cc')
-rw-r--r-- | net/base/cert_verifier_unittest.cc | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/net/base/cert_verifier_unittest.cc b/net/base/cert_verifier_unittest.cc new file mode 100644 index 0000000..ca5e1f4 --- /dev/null +++ b/net/base/cert_verifier_unittest.cc @@ -0,0 +1,260 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/cert_verifier.h" + +#include "base/callback.h" +#include "base/file_path.h" +#include "base/stringprintf.h" +#include "net/base/cert_test_util.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "net/base/x509_certificate.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +class TestTimeService : public CertVerifier::TimeService { + public: + // CertVerifier::TimeService methods: + virtual base::Time Now() { return current_time_; } + + void set_current_time(base::Time now) { current_time_ = now; } + + private: + base::Time current_time_; +}; + +class CertVerifierTest : public testing::Test { +}; + +class ExplodingCallback : public CallbackRunner<Tuple1<int> > { + public: + virtual void RunWithParams(const Tuple1<int>& params) { + FAIL(); + } +}; + +// Tests a cache hit, which should results in synchronous completion. +TEST_F(CertVerifierTest, CacheHit) { + TestTimeService* time_service = new TestTimeService; + base::Time current_time = base::Time::Now(); + time_service->set_current_time(current_time); + CertVerifier verifier(time_service); + + FilePath certs_dir = GetTestCertsDirectory(); + scoped_refptr<X509Certificate> google_cert( + ImportCertFromFile(certs_dir, "google.single.der")); + ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); + + int error; + CertVerifyResult verify_result; + TestCompletionCallback callback; + CertVerifier::RequestHandle request_handle; + + error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, + &callback, &request_handle); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle != NULL); + error = callback.WaitForResult(); + ASSERT_TRUE(IsCertificateError(error)); + ASSERT_EQ(1u, verifier.requests()); + ASSERT_EQ(0u, verifier.cache_hits()); + ASSERT_EQ(0u, verifier.inflight_joins()); + + error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, + &callback, &request_handle); + // Synchronous completion. + ASSERT_NE(ERR_IO_PENDING, error); + ASSERT_TRUE(IsCertificateError(error)); + ASSERT_TRUE(request_handle == NULL); + ASSERT_EQ(2u, verifier.requests()); + ASSERT_EQ(1u, verifier.cache_hits()); + ASSERT_EQ(0u, verifier.inflight_joins()); +} + +// Tests an inflight join. +TEST_F(CertVerifierTest, InflightJoin) { + TestTimeService* time_service = new TestTimeService; + base::Time current_time = base::Time::Now(); + time_service->set_current_time(current_time); + CertVerifier verifier(time_service); + + FilePath certs_dir = GetTestCertsDirectory(); + scoped_refptr<X509Certificate> google_cert( + ImportCertFromFile(certs_dir, "google.single.der")); + ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); + + int error; + CertVerifyResult verify_result; + TestCompletionCallback callback; + CertVerifier::RequestHandle request_handle; + CertVerifyResult verify_result2; + TestCompletionCallback callback2; + CertVerifier::RequestHandle request_handle2; + + error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, + &callback, &request_handle); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle != NULL); + error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result2, + &callback2, &request_handle2); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle2 != NULL); + error = callback.WaitForResult(); + ASSERT_TRUE(IsCertificateError(error)); + error = callback2.WaitForResult(); + ASSERT_TRUE(IsCertificateError(error)); + ASSERT_EQ(2u, verifier.requests()); + ASSERT_EQ(0u, verifier.cache_hits()); + ASSERT_EQ(1u, verifier.inflight_joins()); +} + +// Tests cache entry expiration. +TEST_F(CertVerifierTest, ExpiredCacheEntry) { + TestTimeService* time_service = new TestTimeService; + base::Time current_time = base::Time::Now(); + time_service->set_current_time(current_time); + CertVerifier verifier(time_service); + + FilePath certs_dir = GetTestCertsDirectory(); + scoped_refptr<X509Certificate> google_cert( + ImportCertFromFile(certs_dir, "google.single.der")); + ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); + + int error; + CertVerifyResult verify_result; + TestCompletionCallback callback; + CertVerifier::RequestHandle request_handle; + + error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, + &callback, &request_handle); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle != NULL); + error = callback.WaitForResult(); + ASSERT_TRUE(IsCertificateError(error)); + ASSERT_EQ(1u, verifier.requests()); + ASSERT_EQ(0u, verifier.cache_hits()); + ASSERT_EQ(0u, verifier.inflight_joins()); + + // Before expiration, should have a cache hit. + error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, + &callback, &request_handle); + // Synchronous completion. + ASSERT_NE(ERR_IO_PENDING, error); + ASSERT_TRUE(IsCertificateError(error)); + ASSERT_TRUE(request_handle == NULL); + ASSERT_EQ(2u, verifier.requests()); + ASSERT_EQ(1u, verifier.cache_hits()); + ASSERT_EQ(0u, verifier.inflight_joins()); + + // After expiration, should not have a cache hit. + ASSERT_EQ(1u, verifier.GetCacheSize()); + current_time += base::TimeDelta::FromMinutes(60); + time_service->set_current_time(current_time); + error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, + &callback, &request_handle); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle != NULL); + ASSERT_EQ(0u, verifier.GetCacheSize()); + error = callback.WaitForResult(); + ASSERT_TRUE(IsCertificateError(error)); + ASSERT_EQ(3u, verifier.requests()); + ASSERT_EQ(1u, verifier.cache_hits()); + ASSERT_EQ(0u, verifier.inflight_joins()); +} + +// Tests a full cache. +TEST_F(CertVerifierTest, FullCache) { + TestTimeService* time_service = new TestTimeService; + base::Time current_time = base::Time::Now(); + time_service->set_current_time(current_time); + CertVerifier verifier(time_service); + + FilePath certs_dir = GetTestCertsDirectory(); + scoped_refptr<X509Certificate> google_cert( + ImportCertFromFile(certs_dir, "google.single.der")); + ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); + + int error; + CertVerifyResult verify_result; + TestCompletionCallback callback; + CertVerifier::RequestHandle request_handle; + + error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, + &callback, &request_handle); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle != NULL); + error = callback.WaitForResult(); + ASSERT_TRUE(IsCertificateError(error)); + ASSERT_EQ(1u, verifier.requests()); + ASSERT_EQ(0u, verifier.cache_hits()); + ASSERT_EQ(0u, verifier.inflight_joins()); + + const unsigned kCacheSize = 256; + + for (unsigned i = 0; i < kCacheSize; i++) { + std::string hostname = base::StringPrintf("www%d.example.com", i + 1); + error = verifier.Verify(google_cert, hostname, 0, &verify_result, + &callback, &request_handle); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle != NULL); + error = callback.WaitForResult(); + ASSERT_TRUE(IsCertificateError(error)); + } + ASSERT_EQ(kCacheSize + 1, verifier.requests()); + ASSERT_EQ(0u, verifier.cache_hits()); + ASSERT_EQ(0u, verifier.inflight_joins()); + + ASSERT_EQ(kCacheSize, verifier.GetCacheSize()); + current_time += base::TimeDelta::FromMinutes(60); + time_service->set_current_time(current_time); + error = verifier.Verify(google_cert, "www999.example.com", 0, &verify_result, + &callback, &request_handle); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle != NULL); + ASSERT_EQ(kCacheSize, verifier.GetCacheSize()); + error = callback.WaitForResult(); + ASSERT_EQ(1u, verifier.GetCacheSize()); + ASSERT_TRUE(IsCertificateError(error)); + ASSERT_EQ(kCacheSize + 2, verifier.requests()); + ASSERT_EQ(0u, verifier.cache_hits()); + ASSERT_EQ(0u, verifier.inflight_joins()); +} + +// Tests that the callback of a canceled request is never made. +TEST_F(CertVerifierTest, CancelRequest) { + CertVerifier verifier; + + FilePath certs_dir = GetTestCertsDirectory(); + scoped_refptr<X509Certificate> google_cert( + ImportCertFromFile(certs_dir, "google.single.der")); + ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert); + + int error; + CertVerifyResult verify_result; + ExplodingCallback exploding_callback; + CertVerifier::RequestHandle request_handle; + + error = verifier.Verify(google_cert, "www.example.com", 0, &verify_result, + &exploding_callback, &request_handle); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle != NULL); + verifier.CancelRequest(request_handle); + + // Issue a few more requests to the worker pool and wait for their + // completion, so that the task of the canceled request (which runs on a + // worker thread) is likely to complete by the end of this test. + TestCompletionCallback callback; + for (int i = 0; i < 5; ++i) { + error = verifier.Verify(google_cert, "www2.example.com", 0, &verify_result, + &callback, &request_handle); + ASSERT_EQ(ERR_IO_PENDING, error); + ASSERT_TRUE(request_handle != NULL); + error = callback.WaitForResult(); + verifier.ClearCache(); + } +} + +} // namespace net |