| Index: net/cert/internal/trust_store_collection_unittest.cc
|
| diff --git a/net/cert/internal/trust_store_collection_unittest.cc b/net/cert/internal/trust_store_collection_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4b19bf10d03a6d52a7461d23662c448296d5c172
|
| --- /dev/null
|
| +++ b/net/cert/internal/trust_store_collection_unittest.cc
|
| @@ -0,0 +1,261 @@
|
| +// Copyright 2016 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/cert/internal/trust_store_collection.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/run_loop.h"
|
| +#include "net/cert/internal/parsed_certificate.h"
|
| +#include "net/cert/internal/test_helpers.h"
|
| +#include "net/cert/internal/trust_store_static.h"
|
| +#include "net/cert/internal/trust_store_test_helpers.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace net {
|
| +
|
| +namespace {
|
| +
|
| +::testing::AssertionResult ReadTestPem(const std::string& file_name,
|
| + const std::string& block_name,
|
| + std::string* result) {
|
| + const PemBlockMapping mappings[] = {
|
| + {block_name.c_str(), result},
|
| + };
|
| +
|
| + return ReadTestDataFromPemFile(file_name, mappings);
|
| +}
|
| +
|
| +::testing::AssertionResult ReadTestCert(
|
| + const std::string& file_name,
|
| + scoped_refptr<ParsedCertificate>* result) {
|
| + std::string der;
|
| + ::testing::AssertionResult r = ReadTestPem(
|
| + "net/data/ssl/certificates/" + file_name, "CERTIFICATE", &der);
|
| + if (!r)
|
| + return r;
|
| + *result = ParsedCertificate::CreateFromCertificateCopy(der, {});
|
| + if (!*result)
|
| + return ::testing::AssertionFailure() << "CreateFromCertificateCopy failed";
|
| + return ::testing::AssertionSuccess();
|
| +}
|
| +
|
| +void NotCalled(bool) {
|
| + FAIL();
|
| +}
|
| +
|
| +// If all the stores in the collection return trust results synchronously, the
|
| +// TrustStoreCollection itself should also return synchronously.
|
| +TEST(TrustStoreCollection, StaticResultTrusted) {
|
| + scoped_refptr<ParsedCertificate> cert;
|
| + ASSERT_TRUE(ReadTestCert("root_ca_cert.pem", &cert));
|
| +
|
| + TrustStoreCollection trust_store_collection;
|
| + TrustStoreStatic trust_store1;
|
| + TrustStoreStatic trust_store2;
|
| + trust_store1.AddTrustedCertificate(cert);
|
| + trust_store2.AddTrustedCertificate(cert);
|
| + trust_store_collection.AddStore(&trust_store1);
|
| + trust_store_collection.AddStore(&trust_store2);
|
| +
|
| + bool trusted = false;
|
| + std::unique_ptr<TrustStore::Request> request;
|
| + trust_store_collection.IsTrustedCertificate(cert, base::Bind(&NotCalled),
|
| + &trusted, &request);
|
| + EXPECT_FALSE(request);
|
| + EXPECT_TRUE(trusted);
|
| +}
|
| +
|
| +// If all the stores in the collection return trust results synchronously, the
|
| +// TrustStoreCollection itself should also return synchronously.
|
| +TEST(TrustStoreCollection, StaticResultNotTrusted) {
|
| + scoped_refptr<ParsedCertificate> cert;
|
| + ASSERT_TRUE(ReadTestCert("root_ca_cert.pem", &cert));
|
| +
|
| + TrustStoreCollection trust_store_collection;
|
| + TrustStoreStatic trust_store1;
|
| + TrustStoreStatic trust_store2;
|
| + trust_store_collection.AddStore(&trust_store1);
|
| + trust_store_collection.AddStore(&trust_store2);
|
| +
|
| + bool trusted = true;
|
| + std::unique_ptr<TrustStore::Request> request;
|
| + trust_store_collection.IsTrustedCertificate(cert, base::Bind(&NotCalled),
|
| + &trusted, &request);
|
| + EXPECT_FALSE(request);
|
| + EXPECT_FALSE(trusted);
|
| +}
|
| +
|
| +// If a store returns a synchronous trusted result, result should be
|
| +// synchronous even if there were already async requests started.
|
| +TEST(TrustStoreCollection, SynchronousTrustedResultTakesPrecedenceOverAsync) {
|
| + scoped_refptr<ParsedCertificate> cert;
|
| + ASSERT_TRUE(ReadTestCert("root_ca_cert.pem", &cert));
|
| +
|
| + TrustStoreCollection trust_store_collection;
|
| + AsyncTrustStoreStatic trust_store1;
|
| + TrustStoreStatic trust_store2;
|
| + trust_store1.AddTrustedCertificate(cert);
|
| + trust_store2.AddTrustedCertificate(cert);
|
| + trust_store_collection.AddStore(&trust_store1);
|
| + trust_store_collection.AddStore(&trust_store2);
|
| +
|
| + bool trusted = false;
|
| + std::unique_ptr<TrustStore::Request> request;
|
| + trust_store_collection.IsTrustedCertificate(cert, base::Bind(&NotCalled),
|
| + &trusted, &request);
|
| + EXPECT_FALSE(request);
|
| + EXPECT_TRUE(trusted);
|
| +}
|
| +
|
| +// If a store returns a synchronous not trusted result and there are other
|
| +// stores that are async, the result should wait for the async result.
|
| +TEST(TrustStoreCollection, SynchronousUntrustedResultFallsBackToAsync) {
|
| + scoped_refptr<ParsedCertificate> cert;
|
| + ASSERT_TRUE(ReadTestCert("root_ca_cert.pem", &cert));
|
| +
|
| + TrustStoreCollection trust_store_collection;
|
| + AsyncTrustStoreStatic trust_store1;
|
| + TrustStoreStatic trust_store2;
|
| + trust_store1.AddTrustedCertificate(cert);
|
| + trust_store_collection.AddStore(&trust_store1);
|
| + trust_store_collection.AddStore(&trust_store2);
|
| +
|
| + TrustResultRecorder result_recorder;
|
| + bool unused_trusted = false;
|
| + std::unique_ptr<TrustStore::Request> request;
|
| + trust_store_collection.IsTrustedCertificate(cert, result_recorder.Callback(),
|
| + &unused_trusted, &request);
|
| + EXPECT_FALSE(unused_trusted);
|
| + ASSERT_TRUE(request);
|
| + EXPECT_TRUE(result_recorder.results().empty());
|
| + result_recorder.Run();
|
| + ASSERT_EQ(1U, result_recorder.results().size());
|
| + EXPECT_TRUE(result_recorder.results()[0]);
|
| +}
|
| +
|
| +// The callback passed into TrustStoreCollection::IsTrustedCertificate should
|
| +// only be called once, even if the collection itself issues multiple requests
|
| +// that would each generate a callback.
|
| +TEST(TrustStoreCollection, CallbackCalledOnlyOnce) {
|
| + scoped_refptr<ParsedCertificate> cert;
|
| + ASSERT_TRUE(ReadTestCert("root_ca_cert.pem", &cert));
|
| +
|
| + TrustStoreCollection trust_store_collection;
|
| + AsyncTrustStoreStatic trust_store1;
|
| + AsyncTrustStoreStatic trust_store2;
|
| + trust_store1.AddTrustedCertificate(cert);
|
| + trust_store2.AddTrustedCertificate(cert);
|
| + trust_store_collection.AddStore(&trust_store1);
|
| + trust_store_collection.AddStore(&trust_store2);
|
| +
|
| + TrustResultRecorder result_recorder;
|
| + bool unused_trusted = false;
|
| + std::unique_ptr<TrustStore::Request> request;
|
| + trust_store_collection.IsTrustedCertificate(cert, result_recorder.Callback(),
|
| + &unused_trusted, &request);
|
| + ASSERT_TRUE(request);
|
| + EXPECT_FALSE(unused_trusted);
|
| + EXPECT_TRUE(result_recorder.results().empty());
|
| + result_recorder.Run();
|
| + ASSERT_EQ(1U, result_recorder.results().size());
|
| + EXPECT_TRUE(result_recorder.results()[0]);
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| + ASSERT_EQ(1U, result_recorder.results().size());
|
| +}
|
| +
|
| +// If the Request is cancelled, the callback should not be called.
|
| +TEST(TrustStoreCollection, RequestDeletedBeforeCallback) {
|
| + scoped_refptr<ParsedCertificate> cert;
|
| + ASSERT_TRUE(ReadTestCert("root_ca_cert.pem", &cert));
|
| +
|
| + TrustStoreCollection trust_store_collection;
|
| + AsyncTrustStoreStatic trust_store1;
|
| + AsyncTrustStoreStatic trust_store2;
|
| + trust_store1.AddTrustedCertificate(cert);
|
| + trust_store2.AddTrustedCertificate(cert);
|
| + trust_store_collection.AddStore(&trust_store1);
|
| + trust_store_collection.AddStore(&trust_store2);
|
| +
|
| + TrustResultRecorder result_recorder;
|
| + bool unused_trusted = false;
|
| + std::unique_ptr<TrustStore::Request> request;
|
| + trust_store_collection.IsTrustedCertificate(
|
| + cert, base::Bind(&TrustResultRecorder::HandleResult,
|
| + base::Unretained(&result_recorder)),
|
| + &unused_trusted, &request);
|
| + ASSERT_TRUE(request);
|
| + EXPECT_FALSE(unused_trusted);
|
| + EXPECT_TRUE(result_recorder.results().empty());
|
| +
|
| + request.reset();
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_TRUE(result_recorder.results().empty());
|
| +}
|
| +
|
| +// If the Request is cancelled after receiving the result, but while there could
|
| +// still be sub-Requests pending, make sure nothing crashes.
|
| +TEST(TrustStoreCollection, RequestDeletedAfterFirstSubCallback) {
|
| + scoped_refptr<ParsedCertificate> cert;
|
| + ASSERT_TRUE(ReadTestCert("root_ca_cert.pem", &cert));
|
| +
|
| + TrustStoreCollection trust_store_collection;
|
| + AsyncTrustStoreStatic trust_store1;
|
| + AsyncTrustStoreStatic trust_store2;
|
| + trust_store1.AddTrustedCertificate(cert);
|
| + trust_store2.AddTrustedCertificate(cert);
|
| + trust_store_collection.AddStore(&trust_store1);
|
| + trust_store_collection.AddStore(&trust_store2);
|
| +
|
| + TrustResultRecorder result_recorder;
|
| + bool unused_trusted = false;
|
| + std::unique_ptr<TrustStore::Request> request;
|
| + trust_store_collection.IsTrustedCertificate(
|
| + cert, base::Bind(&TrustResultRecorder::HandleResult,
|
| + base::Unretained(&result_recorder)),
|
| + &unused_trusted, &request);
|
| + ASSERT_TRUE(request);
|
| + EXPECT_FALSE(unused_trusted);
|
| + EXPECT_TRUE(result_recorder.results().empty());
|
| + result_recorder.Run();
|
| + ASSERT_EQ(1U, result_recorder.results().size());
|
| + EXPECT_TRUE(result_recorder.results()[0]);
|
| +
|
| + request.reset();
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| + ASSERT_EQ(1U, result_recorder.results().size());
|
| +}
|
| +
|
| +// If the Request is cancelled during the callback, shouldn't crash.
|
| +TEST(TrustStoreCollection, RequestDeletedDuringCallback) {
|
| + scoped_refptr<ParsedCertificate> cert;
|
| + ASSERT_TRUE(ReadTestCert("root_ca_cert.pem", &cert));
|
| +
|
| + TrustStoreCollection trust_store_collection;
|
| + AsyncTrustStoreStatic trust_store1;
|
| + AsyncTrustStoreStatic trust_store2;
|
| + trust_store1.AddTrustedCertificate(cert);
|
| + trust_store2.AddTrustedCertificate(cert);
|
| + trust_store_collection.AddStore(&trust_store1);
|
| + trust_store_collection.AddStore(&trust_store2);
|
| +
|
| + bool unused_trusted = false;
|
| + base::RunLoop run_loop;
|
| + std::unique_ptr<TrustStore::Request> request;
|
| + trust_store_collection.IsTrustedCertificate(
|
| + cert, base::Bind(&TrustRequestDeleter, &request, run_loop.QuitClosure()),
|
| + &unused_trusted, &request);
|
| + ASSERT_TRUE(request);
|
| + run_loop.Run();
|
| + ASSERT_FALSE(request);
|
| + base::RunLoop().RunUntilIdle();
|
| +}
|
| +
|
| +
|
| +} // namespace
|
| +
|
| +} // namespace net
|
|
|