Index: net/base/origin_bound_cert_service_unittest.cc |
=================================================================== |
--- net/base/origin_bound_cert_service_unittest.cc (revision 95321) |
+++ net/base/origin_bound_cert_service_unittest.cc (working copy) |
@@ -7,57 +7,165 @@ |
#include <string> |
#include <vector> |
-#include "base/memory/ref_counted.h" |
+#include "base/memory/scoped_ptr.h" |
#include "crypto/rsa_private_key.h" |
#include "net/base/default_origin_bound_cert_store.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 OriginBoundCertServiceTest : public testing::Test { |
+}; |
+ |
+class ExplodingCallback : public CallbackRunner<Tuple1<int> > { |
+ public: |
+ virtual void RunWithParams(const Tuple1<int>& params) { |
+ FAIL(); |
+ } |
+}; |
+ |
// See http://crbug.com/91512 - implement OpenSSL version of CreateSelfSigned. |
#if !defined(USE_OPENSSL) |
-TEST(OriginBoundCertServiceTest, DuplicateCertTest) { |
- scoped_refptr<OriginBoundCertService> service( |
+TEST_F(OriginBoundCertServiceTest, CacheHit) { |
+ scoped_ptr<OriginBoundCertService> service( |
new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); |
- std::string origin1("https://encrypted.google.com/"); |
- std::string origin2("https://www.verisign.com/"); |
+ std::string origin("https://encrypted.google.com:443"); |
- // The store should start out empty and should increment appropriately. |
- std::string private_key_info_1a, der_cert_1a; |
- EXPECT_EQ(0, service->GetCertCount()); |
- EXPECT_TRUE(service->GetOriginBoundCert( |
- origin1, &private_key_info_1a, &der_cert_1a)); |
- EXPECT_EQ(1, service->GetCertCount()); |
+ int error; |
+ TestCompletionCallback callback; |
+ OriginBoundCertService::RequestHandle request_handle; |
- // We should get the same cert and key for the same origin. |
- std::string private_key_info_1b, der_cert_1b; |
- EXPECT_TRUE(service->GetOriginBoundCert( |
- origin1, &private_key_info_1b, &der_cert_1b)); |
- EXPECT_EQ(1, service->GetCertCount()); |
- EXPECT_EQ(private_key_info_1a, private_key_info_1b); |
- EXPECT_EQ(der_cert_1a, der_cert_1b); |
+ // Asynchronous completion. |
+ std::string private_key_info1, der_cert1; |
+ EXPECT_EQ(0, service->cert_count()); |
+ error = service->GetOriginBoundCert( |
+ origin, &private_key_info1, &der_cert1, &callback, &request_handle); |
+ EXPECT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request_handle != NULL); |
+ error = callback.WaitForResult(); |
+ EXPECT_EQ(OK, error); |
+ EXPECT_EQ(1, service->cert_count()); |
+ EXPECT_FALSE(private_key_info1.empty()); |
+ EXPECT_FALSE(der_cert1.empty()); |
- // We should get a different cert and key for different origins. |
- std::string private_key_info_2, der_cert_2; |
- EXPECT_TRUE(service->GetOriginBoundCert( |
- origin2, &private_key_info_2, &der_cert_2)); |
- EXPECT_EQ(2, service->GetCertCount()); |
- EXPECT_NE(private_key_info_1a, private_key_info_2); |
- EXPECT_NE(der_cert_1a, der_cert_2); |
+ // Synchronous completion. |
+ std::string private_key_info2, der_cert2; |
+ error = service->GetOriginBoundCert( |
+ origin, &private_key_info2, &der_cert2, &callback, &request_handle); |
+ EXPECT_TRUE(request_handle == NULL); |
+ EXPECT_EQ(OK, error); |
+ EXPECT_EQ(1, service->cert_count()); |
+ |
+ EXPECT_EQ(private_key_info1, private_key_info2); |
+ EXPECT_EQ(der_cert1, der_cert2); |
+ |
+ EXPECT_EQ(2u, service->requests()); |
+ EXPECT_EQ(1u, service->cert_store_hits()); |
+ EXPECT_EQ(0u, service->inflight_joins()); |
} |
-TEST(OriginBoundCertServiceTest, ExtractValuesFromBytes) { |
- scoped_refptr<OriginBoundCertService> service( |
+TEST_F(OriginBoundCertServiceTest, StoreCerts) { |
+ scoped_ptr<OriginBoundCertService> service( |
new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); |
- std::string origin("https://encrypted.google.com/"); |
+ int error; |
+ TestCompletionCallback callback; |
+ OriginBoundCertService::RequestHandle request_handle; |
+ |
+ std::string origin1("https://encrypted.google.com:443"); |
+ std::string private_key_info1, der_cert1; |
+ EXPECT_EQ(0, service->cert_count()); |
+ error = service->GetOriginBoundCert( |
+ origin1, &private_key_info1, &der_cert1, &callback, &request_handle); |
+ EXPECT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request_handle != NULL); |
+ error = callback.WaitForResult(); |
+ EXPECT_EQ(OK, error); |
+ EXPECT_EQ(1, service->cert_count()); |
+ |
+ std::string origin2("https://www.verisign.com:443"); |
+ std::string private_key_info2, der_cert2; |
+ error = service->GetOriginBoundCert( |
+ origin2, &private_key_info2, &der_cert2, &callback, &request_handle); |
+ EXPECT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request_handle != NULL); |
+ error = callback.WaitForResult(); |
+ EXPECT_EQ(OK, error); |
+ EXPECT_EQ(2, service->cert_count()); |
+ |
+ std::string origin3("https://www.twitter.com:443"); |
+ std::string private_key_info3, der_cert3; |
+ error = service->GetOriginBoundCert( |
+ origin3, &private_key_info3, &der_cert3, &callback, &request_handle); |
+ EXPECT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request_handle != NULL); |
+ error = callback.WaitForResult(); |
+ EXPECT_EQ(OK, error); |
+ EXPECT_EQ(3, service->cert_count()); |
+ |
+ EXPECT_NE(private_key_info1, private_key_info2); |
+ EXPECT_NE(der_cert1, der_cert2); |
+ EXPECT_NE(private_key_info1, private_key_info3); |
+ EXPECT_NE(der_cert1, der_cert3); |
+ EXPECT_NE(private_key_info2, private_key_info3); |
+ EXPECT_NE(der_cert2, der_cert3); |
+} |
+ |
+// Tests an inflight join. |
+TEST_F(OriginBoundCertServiceTest, InflightJoin) { |
+ scoped_ptr<OriginBoundCertService> service( |
+ new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); |
+ std::string origin("https://encrypted.google.com:443"); |
+ int error; |
+ |
+ std::string private_key_info1, der_cert1; |
+ TestCompletionCallback callback1; |
+ OriginBoundCertService::RequestHandle request_handle1; |
+ |
+ std::string private_key_info2, der_cert2; |
+ TestCompletionCallback callback2; |
+ OriginBoundCertService::RequestHandle request_handle2; |
+ |
+ error = service->GetOriginBoundCert( |
+ origin, &private_key_info1, &der_cert1, &callback1, &request_handle1); |
+ EXPECT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request_handle1 != NULL); |
+ error = service->GetOriginBoundCert( |
+ origin, &private_key_info2, &der_cert2, &callback2, &request_handle2); |
+ EXPECT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request_handle2 != NULL); |
+ |
+ error = callback1.WaitForResult(); |
+ EXPECT_EQ(OK, error); |
+ error = callback2.WaitForResult(); |
+ EXPECT_EQ(OK, error); |
+ |
+ EXPECT_EQ(2u, service->requests()); |
+ EXPECT_EQ(0u, service->cert_store_hits()); |
+ EXPECT_EQ(1u, service->inflight_joins()); |
+} |
+ |
+TEST_F(OriginBoundCertServiceTest, ExtractValuesFromBytes) { |
+ scoped_ptr<OriginBoundCertService> service( |
+ new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); |
+ std::string origin("https://encrypted.google.com:443"); |
std::string private_key_info, der_cert; |
- EXPECT_TRUE(service->GetOriginBoundCert( |
- origin, &private_key_info, &der_cert)); |
+ int error; |
+ TestCompletionCallback callback; |
+ OriginBoundCertService::RequestHandle request_handle; |
+ |
+ error = service->GetOriginBoundCert( |
+ origin, &private_key_info, &der_cert, &callback, &request_handle); |
+ EXPECT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request_handle != NULL); |
+ error = callback.WaitForResult(); |
+ EXPECT_EQ(OK, error); |
+ |
+ // Check that we can retrieve the key from the bytes. |
std::vector<uint8> key_vec(private_key_info.begin(), private_key_info.end()); |
- |
- // Check that we can retrieve the key pair from the bytes. |
scoped_ptr<crypto::RSAPrivateKey> private_key( |
crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vec)); |
EXPECT_TRUE(private_key != NULL); |
@@ -68,6 +176,42 @@ |
EXPECT_TRUE(x509cert != NULL); |
} |
+// Tests that the callback of a canceled request is never made. |
+TEST_F(OriginBoundCertServiceTest, CancelRequest) { |
+ scoped_ptr<OriginBoundCertService> service( |
+ new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); |
+ std::string origin("https://encrypted.google.com:443"); |
+ std::string private_key_info, der_cert; |
+ int error; |
+ ExplodingCallback exploding_callback; |
+ OriginBoundCertService::RequestHandle request_handle; |
+ |
+ error = service->GetOriginBoundCert(origin, |
+ &private_key_info, |
+ &der_cert, |
+ &exploding_callback, |
+ &request_handle); |
+ EXPECT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request_handle != NULL); |
+ service->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 = service->GetOriginBoundCert( |
+ "https://encrypted.google.com:" + std::string(1, (char) ('1' + i)), |
+ &private_key_info, |
+ &der_cert, |
+ &callback, |
+ &request_handle); |
+ EXPECT_EQ(ERR_IO_PENDING, error); |
+ EXPECT_TRUE(request_handle != NULL); |
+ error = callback.WaitForResult(); |
+ } |
+} |
+ |
#endif // !defined(USE_OPENSSL) |
} // namespace net |