Index: net/base/default_server_bound_cert_store_unittest.cc |
diff --git a/net/base/default_server_bound_cert_store_unittest.cc b/net/base/default_server_bound_cert_store_unittest.cc |
index bc953984f6a40f3dd032c3ea1e702fef12a75e19..df6009ff3595bd6d6a3a6f2288fbb6a1bf743411 100644 |
--- a/net/base/default_server_bound_cert_store_unittest.cc |
+++ b/net/base/default_server_bound_cert_store_unittest.cc |
@@ -12,19 +12,67 @@ |
#include "base/compiler_specific.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace net { |
+namespace { |
+ |
+void CallCounter(int* counter) { |
+ (*counter)++; |
+} |
+ |
+void NotCalled() { |
+ ADD_FAILURE() << "Unexpected callback execution."; |
+} |
+ |
+void GetCertCallbackNotCalled(const std::string& server_identifier, |
+ SSLClientCertType type, |
+ base::Time expiration_time, |
+ const std::string& private_key_result, |
+ const std::string& cert_result) { |
+ ADD_FAILURE() << "Unexpected callback execution."; |
+} |
+ |
+class AsyncGetCertHelper { |
+ public: |
+ AsyncGetCertHelper() : called_(false) {} |
+ |
+ void Callback(const std::string& server_identifier, |
+ SSLClientCertType type, |
+ base::Time expiration_time, |
+ const std::string& private_key_result, |
+ const std::string& cert_result) { |
+ server_identifier_ = server_identifier; |
+ type_ = type; |
+ expiration_time_ = expiration_time; |
+ private_key_ = private_key_result; |
+ cert_ = cert_result; |
+ called_ = true; |
+ } |
+ |
+ std::string server_identifier_; |
+ SSLClientCertType type_; |
+ base::Time expiration_time_; |
+ std::string private_key_; |
+ std::string cert_; |
+ bool called_; |
+}; |
+ |
+void GetAllCallback( |
+ ServerBoundCertStore::ServerBoundCertList* dest, |
+ const ServerBoundCertStore::ServerBoundCertList& result) { |
+ *dest = result; |
+} |
+ |
class MockPersistentStore |
: public DefaultServerBoundCertStore::PersistentStore { |
public: |
MockPersistentStore(); |
// DefaultServerBoundCertStore::PersistentStore implementation. |
- virtual bool Load( |
- std::vector<DefaultServerBoundCertStore::ServerBoundCert*>* certs) |
- OVERRIDE; |
+ virtual void Load(const LoadedCallback& loaded_callback) OVERRIDE; |
virtual void AddServerBoundCert( |
const DefaultServerBoundCertStore::ServerBoundCert& cert) OVERRIDE; |
virtual void DeleteServerBoundCert( |
@@ -44,8 +92,9 @@ class MockPersistentStore |
MockPersistentStore::MockPersistentStore() {} |
-bool MockPersistentStore::Load( |
- std::vector<DefaultServerBoundCertStore::ServerBoundCert*>* certs) { |
+void MockPersistentStore::Load(const LoadedCallback& loaded_callback) { |
+ scoped_ptr<ScopedVector<DefaultServerBoundCertStore::ServerBoundCert> > |
+ certs(new ScopedVector<DefaultServerBoundCertStore::ServerBoundCert>()); |
ServerBoundCertMap::iterator it; |
for (it = origin_certs_.begin(); it != origin_certs_.end(); ++it) { |
@@ -53,7 +102,8 @@ bool MockPersistentStore::Load( |
new DefaultServerBoundCertStore::ServerBoundCert(it->second)); |
} |
- return true; |
+ MessageLoop::current()->PostTask( |
+ FROM_HERE, base::Bind(loaded_callback, base::Passed(&certs))); |
} |
void MockPersistentStore::AddServerBoundCert( |
@@ -74,6 +124,8 @@ void MockPersistentStore::Flush(const base::Closure& completion_task) { |
MockPersistentStore::~MockPersistentStore() {} |
+} // namespace |
+ |
TEST(DefaultServerBoundCertStoreTest, TestLoading) { |
scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); |
@@ -94,13 +146,16 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) { |
// Make sure certs load properly. |
DefaultServerBoundCertStore store(persistent_store.get()); |
- EXPECT_EQ(2, store.GetCertCount()); |
+ // Load has not occurred yet. |
+ EXPECT_EQ(0, store.GetCertCount()); |
store.SetServerBoundCert( |
"verisign.com", |
CLIENT_CERT_RSA_SIGN, |
base::Time(), |
base::Time(), |
"e", "f"); |
+ // Wait for load & queued set task. |
+ MessageLoop::current()->RunUntilIdle(); |
EXPECT_EQ(2, store.GetCertCount()); |
store.SetServerBoundCert( |
"twitter.com", |
@@ -108,22 +163,25 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) { |
base::Time(), |
base::Time(), |
"g", "h"); |
+ // Set should be synchronous now that load is done. |
EXPECT_EQ(3, store.GetCertCount()); |
} |
+//TODO(mattm): add more tests of without a persistent store? |
TEST(DefaultServerBoundCertStoreTest, TestSettingAndGetting) { |
+ // No persistent store, all calls will be synchronous. |
DefaultServerBoundCertStore store(NULL); |
SSLClientCertType type; |
- base::Time creation_time; |
base::Time expiration_time; |
std::string private_key, cert; |
EXPECT_EQ(0, store.GetCertCount()); |
- EXPECT_FALSE(store.GetServerBoundCert("verisign.com", |
- &type, |
- &creation_time, |
- &expiration_time, |
- &private_key, |
- &cert)); |
+ EXPECT_TRUE(store.GetServerBoundCert("verisign.com", |
+ &type, |
+ &expiration_time, |
+ &private_key, |
+ &cert, |
+ base::Bind(&GetCertCallbackNotCalled))); |
+ EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, type); |
EXPECT_TRUE(private_key.empty()); |
EXPECT_TRUE(cert.empty()); |
store.SetServerBoundCert( |
@@ -134,12 +192,11 @@ TEST(DefaultServerBoundCertStoreTest, TestSettingAndGetting) { |
"i", "j"); |
EXPECT_TRUE(store.GetServerBoundCert("verisign.com", |
&type, |
- &creation_time, |
&expiration_time, |
&private_key, |
- &cert)); |
+ &cert, |
+ base::Bind(&GetCertCallbackNotCalled))); |
EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type); |
- EXPECT_EQ(123, creation_time.ToInternalValue()); |
EXPECT_EQ(456, expiration_time.ToInternalValue()); |
EXPECT_EQ("i", private_key); |
EXPECT_EQ("j", cert); |
@@ -150,7 +207,6 @@ TEST(DefaultServerBoundCertStoreTest, TestDuplicateCerts) { |
DefaultServerBoundCertStore store(persistent_store.get()); |
SSLClientCertType type; |
- base::Time creation_time; |
base::Time expiration_time; |
std::string private_key, cert; |
EXPECT_EQ(0, store.GetCertCount()); |
@@ -167,25 +223,57 @@ TEST(DefaultServerBoundCertStoreTest, TestDuplicateCerts) { |
base::Time::FromInternalValue(4567), |
"c", "d"); |
+ // Wait for load & queued set tasks. |
+ MessageLoop::current()->RunUntilIdle(); |
EXPECT_EQ(1, store.GetCertCount()); |
EXPECT_TRUE(store.GetServerBoundCert("verisign.com", |
&type, |
- &creation_time, |
&expiration_time, |
&private_key, |
- &cert)); |
+ &cert, |
+ base::Bind(&GetCertCallbackNotCalled))); |
EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type); |
- EXPECT_EQ(456, creation_time.ToInternalValue()); |
EXPECT_EQ(4567, expiration_time.ToInternalValue()); |
EXPECT_EQ("c", private_key); |
EXPECT_EQ("d", cert); |
} |
+TEST(DefaultServerBoundCertStoreTest, TestAsyncGet) { |
+ scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); |
+ persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( |
+ "verisign.com", |
+ CLIENT_CERT_RSA_SIGN, |
+ base::Time::FromInternalValue(123), |
+ base::Time::FromInternalValue(1234), |
+ "a", "b")); |
+ |
+ DefaultServerBoundCertStore store(persistent_store.get()); |
+ AsyncGetCertHelper helper; |
+ SSLClientCertType type; |
+ base::Time expiration_time; |
+ std::string private_key; |
+ std::string cert = "not set"; |
+ EXPECT_EQ(0, store.GetCertCount()); |
+ EXPECT_FALSE(store.GetServerBoundCert( |
+ "verisign.com", &type, &expiration_time, &private_key, &cert, |
+ base::Bind(&AsyncGetCertHelper::Callback, base::Unretained(&helper)))); |
+ |
+ // Wait for load & queued get tasks. |
+ MessageLoop::current()->RunUntilIdle(); |
+ EXPECT_EQ(1, store.GetCertCount()); |
+ EXPECT_EQ("not set", cert); |
+ EXPECT_TRUE(helper.called_); |
+ EXPECT_EQ("verisign.com", helper.server_identifier_); |
+ EXPECT_EQ(CLIENT_CERT_RSA_SIGN, helper.type_); |
+ EXPECT_EQ(1234, helper.expiration_time_.ToInternalValue()); |
+ EXPECT_EQ("a", helper.private_key_); |
+ EXPECT_EQ("b", helper.cert_); |
+} |
+ |
TEST(DefaultServerBoundCertStoreTest, TestDeleteAll) { |
scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); |
DefaultServerBoundCertStore store(persistent_store.get()); |
- EXPECT_EQ(0, store.GetCertCount()); |
store.SetServerBoundCert( |
"verisign.com", |
CLIENT_CERT_RSA_SIGN, |
@@ -204,18 +292,53 @@ TEST(DefaultServerBoundCertStoreTest, TestDeleteAll) { |
base::Time(), |
base::Time(), |
"e", "f"); |
+ // Wait for load & queued set tasks. |
+ MessageLoop::current()->RunUntilIdle(); |
EXPECT_EQ(3, store.GetCertCount()); |
- store.DeleteAll(); |
+ int delete_finished = 0; |
+ store.DeleteAll(base::Bind(&CallCounter, &delete_finished)); |
+ ASSERT_EQ(1, delete_finished); |
EXPECT_EQ(0, store.GetCertCount()); |
} |
+TEST(DefaultServerBoundCertStoreTest, TestAsyncGetAndDeleteAll) { |
+ scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); |
+ persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( |
+ "verisign.com", |
+ CLIENT_CERT_RSA_SIGN, |
+ base::Time(), |
+ base::Time(), |
+ "a", "b")); |
+ persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( |
+ "google.com", |
+ CLIENT_CERT_RSA_SIGN, |
+ base::Time(), |
+ base::Time(), |
+ "c", "d")); |
+ |
+ ServerBoundCertStore::ServerBoundCertList pre_certs; |
+ ServerBoundCertStore::ServerBoundCertList post_certs; |
+ int delete_finished = 0; |
+ DefaultServerBoundCertStore store(persistent_store.get()); |
+ |
+ store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &pre_certs)); |
+ store.DeleteAll(base::Bind(&CallCounter, &delete_finished)); |
+ store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &post_certs)); |
+ // Tasks have not run yet. |
+ EXPECT_EQ(0u, pre_certs.size()); |
+ // Wait for load & queued tasks. |
+ MessageLoop::current()->RunUntilIdle(); |
+ EXPECT_EQ(0, store.GetCertCount()); |
+ EXPECT_EQ(2u, pre_certs.size()); |
+ EXPECT_EQ(0u, post_certs.size()); |
+} |
+ |
TEST(DefaultServerBoundCertStoreTest, TestDelete) { |
scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); |
DefaultServerBoundCertStore store(persistent_store.get()); |
SSLClientCertType type; |
- base::Time creation_time; |
base::Time expiration_time; |
std::string private_key, cert; |
EXPECT_EQ(0, store.GetCertCount()); |
@@ -225,6 +348,9 @@ TEST(DefaultServerBoundCertStoreTest, TestDelete) { |
base::Time(), |
base::Time(), |
"a", "b"); |
+ // Wait for load & queued set task. |
+ MessageLoop::current()->RunUntilIdle(); |
+ |
store.SetServerBoundCert( |
"google.com", |
CLIENT_CERT_ECDSA_SIGN, |
@@ -233,28 +359,92 @@ TEST(DefaultServerBoundCertStoreTest, TestDelete) { |
"c", "d"); |
EXPECT_EQ(2, store.GetCertCount()); |
- store.DeleteServerBoundCert("verisign.com"); |
+ int delete_finished = 0; |
+ store.DeleteServerBoundCert("verisign.com", |
+ base::Bind(&CallCounter, &delete_finished)); |
+ ASSERT_EQ(1, delete_finished); |
EXPECT_EQ(1, store.GetCertCount()); |
- EXPECT_FALSE(store.GetServerBoundCert("verisign.com", |
- &type, |
- &creation_time, |
- &expiration_time, |
- &private_key, |
- &cert)); |
+ EXPECT_TRUE(store.GetServerBoundCert("verisign.com", |
+ &type, |
+ &expiration_time, |
+ &private_key, |
+ &cert, |
+ base::Bind(&GetCertCallbackNotCalled))); |
+ EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, type); |
EXPECT_TRUE(store.GetServerBoundCert("google.com", |
&type, |
- &creation_time, |
&expiration_time, |
&private_key, |
- &cert)); |
- store.DeleteServerBoundCert("google.com"); |
+ &cert, |
+ base::Bind(&GetCertCallbackNotCalled))); |
+ EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type); |
+ int delete2_finished = 0; |
+ store.DeleteServerBoundCert("google.com", |
+ base::Bind(&CallCounter, &delete2_finished)); |
+ ASSERT_EQ(1, delete2_finished); |
EXPECT_EQ(0, store.GetCertCount()); |
- EXPECT_FALSE(store.GetServerBoundCert("google.com", |
- &type, |
- &creation_time, |
- &expiration_time, |
- &private_key, |
- &cert)); |
+ EXPECT_TRUE(store.GetServerBoundCert("google.com", |
+ &type, |
+ &expiration_time, |
+ &private_key, |
+ &cert, |
+ base::Bind(&GetCertCallbackNotCalled))); |
+ EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, type); |
+} |
+ |
+TEST(DefaultServerBoundCertStoreTest, TestAsyncDelete) { |
+ scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); |
+ persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( |
+ "a.com", |
+ CLIENT_CERT_RSA_SIGN, |
+ base::Time::FromInternalValue(1), |
+ base::Time::FromInternalValue(2), |
+ "a", "b")); |
+ persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( |
+ "b.com", |
+ CLIENT_CERT_RSA_SIGN, |
+ base::Time::FromInternalValue(3), |
+ base::Time::FromInternalValue(4), |
+ "c", "d")); |
+ DefaultServerBoundCertStore store(persistent_store.get()); |
+ int delete_finished = 0; |
+ store.DeleteServerBoundCert("a.com", |
+ base::Bind(&CallCounter, &delete_finished)); |
+ |
+ AsyncGetCertHelper a_helper; |
+ AsyncGetCertHelper b_helper; |
+ SSLClientCertType type; |
+ base::Time expiration_time; |
+ std::string private_key; |
+ std::string cert = "not set"; |
+ EXPECT_EQ(0, store.GetCertCount()); |
+ EXPECT_FALSE(store.GetServerBoundCert( |
+ "a.com", &type, &expiration_time, &private_key, &cert, |
+ base::Bind(&AsyncGetCertHelper::Callback, base::Unretained(&a_helper)))); |
+ EXPECT_FALSE(store.GetServerBoundCert( |
+ "b.com", &type, &expiration_time, &private_key, &cert, |
+ base::Bind(&AsyncGetCertHelper::Callback, base::Unretained(&b_helper)))); |
+ |
+ EXPECT_EQ(0, delete_finished); |
+ EXPECT_FALSE(a_helper.called_); |
+ EXPECT_FALSE(b_helper.called_); |
+ // Wait for load & queued tasks. |
+ MessageLoop::current()->RunUntilIdle(); |
+ EXPECT_EQ(1, delete_finished); |
+ EXPECT_EQ(1, store.GetCertCount()); |
+ EXPECT_EQ("not set", cert); |
+ EXPECT_TRUE(a_helper.called_); |
+ EXPECT_EQ("a.com", a_helper.server_identifier_); |
+ EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, a_helper.type_); |
+ EXPECT_EQ(0, a_helper.expiration_time_.ToInternalValue()); |
+ EXPECT_EQ("", a_helper.private_key_); |
+ EXPECT_EQ("", a_helper.cert_); |
+ EXPECT_TRUE(b_helper.called_); |
+ EXPECT_EQ("b.com", b_helper.server_identifier_); |
+ EXPECT_EQ(CLIENT_CERT_RSA_SIGN, b_helper.type_); |
+ EXPECT_EQ(4, b_helper.expiration_time_.ToInternalValue()); |
+ EXPECT_EQ("c", b_helper.private_key_); |
+ EXPECT_EQ("d", b_helper.cert_); |
} |
TEST(DefaultServerBoundCertStoreTest, TestGetAll) { |
@@ -286,10 +476,12 @@ TEST(DefaultServerBoundCertStoreTest, TestGetAll) { |
base::Time(), |
base::Time(), |
"g", "h"); |
+ // Wait for load & queued set tasks. |
+ MessageLoop::current()->RunUntilIdle(); |
EXPECT_EQ(4, store.GetCertCount()); |
ServerBoundCertStore::ServerBoundCertList certs; |
- store.GetAllServerBoundCerts(&certs); |
+ store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &certs)); |
EXPECT_EQ(4u, certs.size()); |
} |
@@ -309,6 +501,8 @@ TEST(DefaultServerBoundCertStoreTest, TestInitializeFrom) { |
base::Time(), |
base::Time(), |
"c", "d"); |
+ // Wait for load & queued set tasks. |
+ MessageLoop::current()->RunUntilIdle(); |
EXPECT_EQ(2, store.GetCertCount()); |
ServerBoundCertStore::ServerBoundCertList source_certs; |
@@ -329,7 +523,60 @@ TEST(DefaultServerBoundCertStoreTest, TestInitializeFrom) { |
EXPECT_EQ(3, store.GetCertCount()); |
ServerBoundCertStore::ServerBoundCertList certs; |
- store.GetAllServerBoundCerts(&certs); |
+ store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &certs)); |
+ ASSERT_EQ(3u, certs.size()); |
+ |
+ ServerBoundCertStore::ServerBoundCertList::iterator cert = certs.begin(); |
+ EXPECT_EQ("both.com", cert->server_identifier()); |
+ EXPECT_EQ("e", cert->private_key()); |
+ |
+ ++cert; |
+ EXPECT_EQ("copied.com", cert->server_identifier()); |
+ EXPECT_EQ("g", cert->private_key()); |
+ |
+ ++cert; |
+ EXPECT_EQ("preexisting.com", cert->server_identifier()); |
+ EXPECT_EQ("a", cert->private_key()); |
+} |
+ |
+TEST(DefaultServerBoundCertStoreTest, TestAsyncInitializeFrom) { |
+ scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); |
+ persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( |
+ "preexisting.com", |
+ CLIENT_CERT_RSA_SIGN, |
+ base::Time(), |
+ base::Time(), |
+ "a", "b")); |
+ persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( |
+ "both.com", |
+ CLIENT_CERT_RSA_SIGN, |
+ base::Time(), |
+ base::Time(), |
+ "c", "d")); |
+ |
+ DefaultServerBoundCertStore store(persistent_store.get()); |
+ ServerBoundCertStore::ServerBoundCertList source_certs; |
+ source_certs.push_back(ServerBoundCertStore::ServerBoundCert( |
+ "both.com", |
+ CLIENT_CERT_RSA_SIGN, |
+ base::Time(), |
+ base::Time(), |
+ // Key differs from above to test that existing entries are overwritten. |
+ "e", "f")); |
+ source_certs.push_back(ServerBoundCertStore::ServerBoundCert( |
+ "copied.com", |
+ CLIENT_CERT_RSA_SIGN, |
+ base::Time(), |
+ base::Time(), |
+ "g", "h")); |
+ store.InitializeFrom(source_certs); |
+ EXPECT_EQ(0, store.GetCertCount()); |
+ // Wait for load & queued tasks. |
+ MessageLoop::current()->RunUntilIdle(); |
+ EXPECT_EQ(3, store.GetCertCount()); |
+ |
+ ServerBoundCertStore::ServerBoundCertList certs; |
+ store.GetAllServerBoundCerts(base::Bind(GetAllCallback, &certs)); |
ASSERT_EQ(3u, certs.size()); |
ServerBoundCertStore::ServerBoundCertList::iterator cert = certs.begin(); |