summaryrefslogtreecommitdiffstats
path: root/net/base/cert_verifier_unittest.cc
diff options
context:
space:
mode:
authorwtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-16 17:27:15 +0000
committerwtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-16 17:27:15 +0000
commit822581d32a6836feae73b96a2ce494a058004423 (patch)
tree925796acd3c3aeaa357378c096c5d9efec31bf36 /net/base/cert_verifier_unittest.cc
parentae89b8d559bfa6b3a2c1d404b21386bcc8995472 (diff)
downloadchromium_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.cc260
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