Home | History | Annotate | Download | only in http
      1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/http/disk_based_cert_cache.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback_helpers.h"
      9 #include "net/base/completion_callback.h"
     10 #include "net/base/io_buffer.h"
     11 #include "net/base/net_errors.h"
     12 #include "net/base/test_completion_callback.h"
     13 #include "net/base/test_data_directory.h"
     14 #include "net/disk_cache/memory/mem_backend_impl.h"
     15 #include "net/http/mock_http_cache.h"
     16 #include "net/test/cert_test_util.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 namespace net {
     20 
     21 namespace {
     22 
     23 // Testing the DiskBasedCertCache requires constant use of the
     24 // certificates in GetTestCertsDirectory(). The TestCertMetaData
     25 // struct stores metadata relevant to the DiskBasedCertCache for
     26 // each used test certificate.
     27 struct TestCertMetaData {
     28   const char* file_name;
     29   const char* cache_key;
     30 };
     31 
     32 const TestCertMetaData kCert1 = {
     33     "root_ca_cert.pem", "cert:738D348A8AFCEC4F79C3E4B1845D985AF601AB0F"};
     34 
     35 const TestCertMetaData kCert2 = {
     36     "ok_cert.pem", "cert:6C9DFD2CFA9885C71BE6DE0EA0CF962AC8F9131B"};
     37 
     38 // MockTransactions are required to use the MockDiskCache backend.
     39 // |key| is a cache key, and is equivalent to the key that will be
     40 // used to store or retrieve certificates in the cache. |test_mode|
     41 // is an integer that is used to indicate properties of the test
     42 // transaction, mostly whether or not it is synchronous.
     43 // For testing the DiskBasedCertCache, other data members of the struct
     44 // are irrelevant. Only one MockTransaction per certificate can be used
     45 // at a time.
     46 MockTransaction CreateMockTransaction(const char* key, int test_mode) {
     47   MockTransaction transaction = {key,  "", base::Time(), "", LOAD_NORMAL,
     48                                  "",   "", base::Time(), "", test_mode,
     49                                  NULL, 0,  OK};
     50 
     51   return transaction;
     52 }
     53 
     54 // Helper class, for use with DiskBasedCertCache::GetCertificate, that will
     55 // store the returned certificate handle and allow users to WaitForResult of
     56 // DiskBasedCertCache::GetCertificate.
     57 class TestGetCallback {
     58  public:
     59   TestGetCallback() : cert_handle_(NULL) {}
     60   ~TestGetCallback() {
     61     if (cert_handle_)
     62       X509Certificate::FreeOSCertHandle(cert_handle_);
     63   }
     64 
     65   // Blocks until the underlying GetCertificate() operation has succeeded.
     66   void WaitForResult() { cb_.WaitForResult(); }
     67 
     68   // Returns a Callback suitable for use with
     69   // DiskBasedCertCache::GetCertificate(). The returned callback is only valid
     70   // while the TestGetCallback object is still valid.
     71   DiskBasedCertCache::GetCallback callback() {
     72     return base::Bind(&TestGetCallback::OnGetComplete, base::Unretained(this));
     73   }
     74 
     75   // Returns the associated certificate handle.
     76   const X509Certificate::OSCertHandle& cert_handle() const {
     77     return cert_handle_;
     78   }
     79 
     80  private:
     81   void OnGetComplete(const X509Certificate::OSCertHandle handle) {
     82     if (handle)
     83       cert_handle_ = X509Certificate::DupOSCertHandle(handle);
     84     cb_.callback().Run(OK);
     85   }
     86 
     87   TestCompletionCallback cb_;
     88   X509Certificate::OSCertHandle cert_handle_;
     89 };
     90 
     91 // Helper class, for use with DiskBasedCertCache::SetCertificate, that will
     92 // store the returned key and allow a user to WaitForResult of
     93 // DiskBasedCertCache::SetCertificate.
     94 class TestSetCallback {
     95  public:
     96   TestSetCallback() {}
     97   ~TestSetCallback() {}
     98 
     99   // Blocks until the underlying SetCertificate() operation has succeeded.
    100   void WaitForResult() { cb_.WaitForResult(); }
    101 
    102   // Returns a Callback suitable for use with
    103   // DiskBasedCertCache::SetCertificate(). The returned callback is only valid
    104   // while the TestSetCallback object is still  valid.
    105   DiskBasedCertCache::SetCallback callback() {
    106     return base::Bind(&TestSetCallback::OnSetComplete, base::Unretained(this));
    107   }
    108 
    109   // Returns the associated certificate handle.
    110   const std::string& key() const { return key_; }
    111 
    112  private:
    113   void OnSetComplete(const std::string& key) {
    114     key_ = key;
    115     cb_.callback().Run(OK);
    116   }
    117 
    118   TestCompletionCallback cb_;
    119   std::string key_;
    120 };
    121 
    122 // Stores the certificate corresponding to |cert_data| in |backend|. If
    123 // |corrupt_data| is true, the certificate will be imported with errors
    124 // so as to mimic a corrupted file on disk.
    125 void ImportCert(disk_cache::Backend* backend,
    126                 const TestCertMetaData& cert_data,
    127                 bool corrupt_data) {
    128   disk_cache::Entry* entry;
    129   TestCompletionCallback callback;
    130   int rv =
    131       backend->CreateEntry(cert_data.cache_key, &entry, callback.callback());
    132   EXPECT_EQ(OK, callback.GetResult(rv));
    133   scoped_refptr<X509Certificate> cert(
    134       ImportCertFromFile(GetTestCertsDirectory(), cert_data.file_name));
    135   std::string write_data;
    136   bool encoded =
    137       X509Certificate::GetDEREncoded(cert->os_cert_handle(), &write_data);
    138   ASSERT_TRUE(encoded);
    139   if (corrupt_data) {
    140     for (size_t i = 0; i < write_data.size(); i += 20)
    141       ++write_data[i];
    142   }
    143   scoped_refptr<IOBuffer> buffer(new IOBuffer(write_data.size()));
    144   memcpy(buffer->data(), write_data.data(), write_data.size());
    145   rv = entry->WriteData(0 /* index */,
    146                         0 /* offset */,
    147                         buffer.get(),
    148                         write_data.size(),
    149                         callback.callback(),
    150                         true /* truncate */);
    151   ASSERT_EQ(static_cast<int>(write_data.size()), callback.GetResult(rv));
    152   entry->Close();
    153 }
    154 
    155 // Checks that the the certificate corresponding to |cert_data| is an existing,
    156 // correctly cached entry in |backend|.
    157 void CheckCertCached(disk_cache::Backend* backend,
    158                      const TestCertMetaData& cert_data) {
    159   disk_cache::Entry* entry;
    160   TestCompletionCallback callback;
    161   int rv = backend->OpenEntry(cert_data.cache_key, &entry, callback.callback());
    162   EXPECT_EQ(OK, callback.GetResult(rv));
    163   scoped_refptr<X509Certificate> cert(
    164       ImportCertFromFile(GetTestCertsDirectory(), cert_data.file_name));
    165   std::string write_data;
    166   bool encoded =
    167       X509Certificate::GetDEREncoded(cert->os_cert_handle(), &write_data);
    168   ASSERT_TRUE(encoded);
    169   int entry_size = entry->GetDataSize(0 /* index */);
    170   scoped_refptr<IOBuffer> buffer(new IOBuffer(entry_size));
    171   rv = entry->ReadData(0 /* index */,
    172                        0 /* offset */,
    173                        buffer.get(),
    174                        entry_size,
    175                        callback.callback());
    176   EXPECT_EQ(entry_size, callback.GetResult(rv));
    177   entry->Close();
    178   X509Certificate::OSCertHandle cached_cert_handle =
    179       X509Certificate::CreateOSCertHandleFromBytes(buffer->data(), entry_size);
    180   EXPECT_TRUE(X509Certificate::IsSameOSCert(cached_cert_handle,
    181                                             cert->os_cert_handle()));
    182   X509Certificate::FreeOSCertHandle(cached_cert_handle);
    183 }
    184 
    185 }  // namespace
    186 
    187 // ----------------------------------------------------------------------------
    188 
    189 // Tests that a certificate can be stored in the cache.
    190 TEST(DiskBasedCertCache, SetCert) {
    191   ScopedMockTransaction trans1(
    192       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    193   MockDiskCache backend;
    194   DiskBasedCertCache cache(&backend);
    195   scoped_refptr<X509Certificate> cert(
    196       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    197   ASSERT_TRUE(cert.get());
    198   TestSetCallback set_callback;
    199 
    200   cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
    201   set_callback.WaitForResult();
    202   EXPECT_EQ(kCert1.cache_key, set_callback.key());
    203   ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
    204 }
    205 
    206 // Tests that a certificate can be retrieved from the cache.
    207 TEST(DiskBasedCertCache, GetCert) {
    208   ScopedMockTransaction trans1(
    209       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    210   MockDiskCache backend;
    211   ASSERT_NO_FATAL_FAILURE(
    212       ImportCert(&backend, kCert1, false /* not corrupted */));
    213   DiskBasedCertCache cache(&backend);
    214   TestGetCallback get_callback;
    215 
    216   cache.GetCertificate(kCert1.cache_key, get_callback.callback());
    217   get_callback.WaitForResult();
    218 
    219   scoped_refptr<X509Certificate> cert(
    220       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    221   EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback.cert_handle(),
    222                                             cert->os_cert_handle()));
    223 }
    224 
    225 // Tests that the DiskBasedCertCache successfully writes to the cache
    226 // if the cache acts synchronously
    227 TEST(DiskBasedCertCache, SyncSet) {
    228   ScopedMockTransaction trans1(
    229       CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_ALL));
    230   MockDiskCache backend;
    231   DiskBasedCertCache cache(&backend);
    232   scoped_refptr<X509Certificate> cert(
    233       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    234   ASSERT_TRUE(cert.get());
    235 
    236   TestSetCallback set_callback;
    237   cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
    238   set_callback.WaitForResult();
    239   EXPECT_EQ(kCert1.cache_key, set_callback.key());
    240   ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
    241 }
    242 
    243 // Tests that the DiskBasedCertCache successfully reads from the cache
    244 // if the cache acts synchronously
    245 TEST(DiskBasedCertCache, SyncGet) {
    246   ScopedMockTransaction trans1(
    247       CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_ALL));
    248   MockDiskCache backend;
    249   ASSERT_NO_FATAL_FAILURE(
    250       (ImportCert(&backend, kCert1, false /* not corrupted */)));
    251   DiskBasedCertCache cache(&backend);
    252   scoped_refptr<X509Certificate> cert(
    253       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    254   ASSERT_TRUE(cert.get());
    255 
    256   TestGetCallback get_callback;
    257   cache.GetCertificate(kCert1.cache_key, get_callback.callback());
    258   get_callback.WaitForResult();
    259   EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback.cert_handle(),
    260                                             cert->os_cert_handle()));
    261 }
    262 
    263 // Tests that GetCertificate will fail on a corrupted certificate.
    264 TEST(DiskBasedCertCache, GetBrokenCert) {
    265   ScopedMockTransaction trans1(
    266       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    267   MockDiskCache backend;
    268   ASSERT_NO_FATAL_FAILURE(ImportCert(&backend, kCert1, true /* corrupted */));
    269   DiskBasedCertCache cache(&backend);
    270   TestGetCallback get_callback;
    271 
    272   cache.GetCertificate(kCert1.cache_key, get_callback.callback());
    273   get_callback.WaitForResult();
    274 
    275   EXPECT_FALSE(get_callback.cert_handle());
    276 }
    277 
    278 // Tests that attempting to retrieve a cert that is not in the cache will
    279 // return NULL.
    280 TEST(DiskBasedCertCache, GetUncachedCert) {
    281   ScopedMockTransaction trans1(
    282       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    283   MockDiskCache backend;
    284   DiskBasedCertCache cache(&backend);
    285   TestGetCallback get_callback;
    286 
    287   cache.GetCertificate(kCert1.cache_key, get_callback.callback());
    288   get_callback.WaitForResult();
    289   EXPECT_EQ(NULL, get_callback.cert_handle());
    290 }
    291 
    292 // Issues two requests to store a certificate in the cache
    293 // (simultaneously), and checks that the DiskBasedCertCache stores the
    294 // certificate to the cache (in one write rather than two).
    295 TEST(DiskBasedCertCache, SetMultiple) {
    296   ScopedMockTransaction trans1(
    297       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    298   MockDiskCache backend;
    299   DiskBasedCertCache cache(&backend);
    300   scoped_refptr<X509Certificate> cert(
    301       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    302   ASSERT_TRUE(cert.get());
    303   TestSetCallback set_callback1, set_callback2;
    304 
    305   // Behind the scenes, these two operations will be combined
    306   // into one operation. IgnoreCallbacks guarantees that the
    307   // first SetCertificate operation is not yet complete when the second
    308   // SetCertificate is called, and then IgnoreCallbacks(false) continues the
    309   // (combined) operation in the |cache|.
    310   MockDiskEntry::IgnoreCallbacks(true);
    311   cache.SetCertificate(cert->os_cert_handle(), set_callback1.callback());
    312   cache.SetCertificate(cert->os_cert_handle(), set_callback2.callback());
    313   MockDiskEntry::IgnoreCallbacks(false);
    314 
    315   set_callback1.WaitForResult();
    316   set_callback2.WaitForResult();
    317   EXPECT_EQ(set_callback1.key(), set_callback2.key());
    318   ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
    319 }
    320 
    321 // Issues two requests to store a certificate in the cache
    322 // because the first transaction finishes before the second
    323 // one is issued, the first cache write is overwritten.
    324 TEST(DiskBasedCertCache, SetOverwrite) {
    325   ScopedMockTransaction trans1(
    326       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    327   MockDiskCache backend;
    328   backend.set_double_create_check(false);
    329   DiskBasedCertCache cache(&backend);
    330   scoped_refptr<X509Certificate> cert(
    331       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    332   ASSERT_TRUE(cert.get());
    333   TestSetCallback set_callback1, set_callback2;
    334 
    335   cache.SetCertificate(cert->os_cert_handle(), set_callback1.callback());
    336   set_callback1.WaitForResult();
    337   cache.SetCertificate(cert->os_cert_handle(), set_callback2.callback());
    338   set_callback2.WaitForResult();
    339 
    340   EXPECT_EQ(set_callback1.key(), set_callback2.key());
    341   ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
    342 }
    343 
    344 // Stores a certificate in the DiskBasedCertCache, then retrieves it
    345 // and makes sure it was retrieved successfully.
    346 TEST(DiskBasedCertCache, SimpleSetAndGet) {
    347   ScopedMockTransaction trans1(
    348       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    349   MockDiskCache backend;
    350   DiskBasedCertCache cache(&backend);
    351   scoped_refptr<X509Certificate> cert(
    352       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    353   ASSERT_TRUE(cert.get());
    354   TestSetCallback set_callback;
    355   TestGetCallback get_callback;
    356 
    357   cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
    358   set_callback.WaitForResult();
    359   cache.GetCertificate(set_callback.key(), get_callback.callback());
    360   get_callback.WaitForResult();
    361   EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback.cert_handle(),
    362                                             cert->os_cert_handle()));
    363 }
    364 
    365 // Tests some basic functionality of the DiskBasedCertCache, with multiple
    366 // set and get operations.
    367 TEST(DiskBasedCertCache, BasicUsage) {
    368   ScopedMockTransaction trans1(
    369       CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_CACHE_START));
    370   ScopedMockTransaction trans2(
    371       CreateMockTransaction(kCert2.cache_key, TEST_MODE_NORMAL));
    372   MockDiskCache backend;
    373   DiskBasedCertCache cache(&backend);
    374   scoped_refptr<X509Certificate> cert1(
    375       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    376   scoped_refptr<X509Certificate> cert2(
    377       ImportCertFromFile(GetTestCertsDirectory(), kCert2.file_name));
    378   ASSERT_TRUE(cert1.get());
    379   ASSERT_TRUE(cert2.get());
    380   ASSERT_FALSE(X509Certificate::IsSameOSCert(cert1->os_cert_handle(),
    381                                              cert2->os_cert_handle()));
    382   TestSetCallback set_callback1, set_callback2;
    383 
    384   // Callbacks are temporarily ignored here to guarantee the asynchronous
    385   // operations of the DiskBasedCertCache are always executed in the same
    386   // order.
    387   MockDiskEntry::IgnoreCallbacks(true);
    388   cache.SetCertificate(cert1->os_cert_handle(), set_callback1.callback());
    389   cache.SetCertificate(cert2->os_cert_handle(), set_callback2.callback());
    390   MockDiskEntry::IgnoreCallbacks(false);
    391   set_callback1.WaitForResult();
    392   set_callback2.WaitForResult();
    393 
    394   TestGetCallback get_callback1, get_callback2;
    395 
    396   MockDiskEntry::IgnoreCallbacks(true);
    397   cache.GetCertificate(set_callback1.key(), get_callback1.callback());
    398   cache.GetCertificate(set_callback2.key(), get_callback2.callback());
    399   MockDiskEntry::IgnoreCallbacks(false);
    400   get_callback1.WaitForResult();
    401   get_callback2.WaitForResult();
    402 
    403   EXPECT_TRUE(X509Certificate::IsSameOSCert(cert1->os_cert_handle(),
    404                                             get_callback1.cert_handle()));
    405   EXPECT_TRUE(X509Certificate::IsSameOSCert(cert2->os_cert_handle(),
    406                                             get_callback2.cert_handle()));
    407 }
    408 
    409 // Test the result of simultaneous requests to store and retrieve a
    410 // certificate from the cache, with the get operation attempting to
    411 // open the cache first and therefore failing to open the entry.
    412 TEST(DiskBasedCertCache, SimultaneousGetSet) {
    413   ScopedMockTransaction trans1(
    414       CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_CACHE_START));
    415   MockDiskCache backend;
    416   DiskBasedCertCache cache(&backend);
    417   scoped_refptr<X509Certificate> cert(
    418       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    419   ASSERT_TRUE(cert.get());
    420 
    421   TestGetCallback get_callback;
    422   TestSetCallback set_callback;
    423 
    424   MockDiskEntry::IgnoreCallbacks(true);
    425   cache.GetCertificate(kCert1.cache_key, get_callback.callback());
    426   cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
    427   MockDiskEntry::IgnoreCallbacks(false);
    428   get_callback.WaitForResult();
    429   set_callback.WaitForResult();
    430 
    431   EXPECT_EQ(NULL, get_callback.cert_handle());
    432   EXPECT_EQ(kCert1.cache_key, set_callback.key());
    433 }
    434 
    435 // Test the result of simultaneous requests to store and retrieve a
    436 // certificate from the cache, with the get operation opening the cache
    437 // after the set operation, leading to a successful read.
    438 TEST(DiskBasedCertCache, SimultaneousSetGet) {
    439   ScopedMockTransaction trans1(
    440       CreateMockTransaction(kCert1.cache_key, TEST_MODE_SYNC_CACHE_START));
    441   MockDiskCache backend;
    442   DiskBasedCertCache cache(&backend);
    443   scoped_refptr<X509Certificate> cert(
    444       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    445   ASSERT_TRUE(cert.get());
    446 
    447   TestSetCallback set_callback;
    448   TestGetCallback get_callback;
    449 
    450   MockDiskEntry::IgnoreCallbacks(true);
    451   cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
    452   cache.GetCertificate(kCert1.cache_key, get_callback.callback());
    453   MockDiskEntry::IgnoreCallbacks(false);
    454   set_callback.WaitForResult();
    455   get_callback.WaitForResult();
    456 
    457   EXPECT_EQ(kCert1.cache_key, set_callback.key());
    458   EXPECT_TRUE(X509Certificate::IsSameOSCert(cert->os_cert_handle(),
    459                                             get_callback.cert_handle()));
    460 }
    461 
    462 // Tests that the DiskBasedCertCache can be deleted without issues when
    463 // there are pending operations in the disk cache.
    464 TEST(DiskBasedCertCache, DeletedCertCache) {
    465   ScopedMockTransaction trans1(
    466       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    467   MockDiskCache backend;
    468   scoped_ptr<DiskBasedCertCache> cache(new DiskBasedCertCache(&backend));
    469   scoped_refptr<X509Certificate> cert(
    470       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    471   ASSERT_TRUE(cert.get());
    472   TestSetCallback set_callback;
    473 
    474   cache->SetCertificate(cert->os_cert_handle(), set_callback.callback());
    475   cache.reset();
    476   set_callback.WaitForResult();
    477   EXPECT_EQ(std::string(), set_callback.key());
    478 }
    479 
    480 // Issues two successive read requests for a certificate, and then
    481 // checks that the DiskBasedCertCache correctly read and recorded
    482 // reading through the in-memory MRU cache.
    483 TEST(DiskBasedCertCache, MemCacheGet) {
    484   ScopedMockTransaction trans1(
    485       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    486   MockDiskCache backend;
    487   ASSERT_NO_FATAL_FAILURE(
    488       ImportCert(&backend, kCert1, false /* not corrupted */));
    489   DiskBasedCertCache cache(&backend);
    490 
    491   TestGetCallback get_callback1, get_callback2;
    492   cache.GetCertificate(kCert1.cache_key, get_callback1.callback());
    493   get_callback1.WaitForResult();
    494   EXPECT_EQ(0U, cache.mem_cache_hits_for_testing());
    495   cache.GetCertificate(kCert1.cache_key, get_callback2.callback());
    496   get_callback2.WaitForResult();
    497   EXPECT_EQ(1U, cache.mem_cache_hits_for_testing());
    498   EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback1.cert_handle(),
    499                                             get_callback2.cert_handle()));
    500 }
    501 
    502 // Reads a corrupted certificate from the disk cache, and then overwrites
    503 // it and checks that the uncorrupted version was stored in the in-memory
    504 // cache.
    505 TEST(DiskBasedCertCache, CorruptOverwrite) {
    506   ScopedMockTransaction trans1(
    507       CreateMockTransaction(kCert1.cache_key, TEST_MODE_NORMAL));
    508   MockDiskCache backend;
    509   backend.set_double_create_check(false);
    510   ASSERT_NO_FATAL_FAILURE(ImportCert(&backend, kCert1, true /* corrupted */));
    511   DiskBasedCertCache cache(&backend);
    512   TestGetCallback get_callback1, get_callback2;
    513 
    514   cache.GetCertificate(kCert1.cache_key, get_callback1.callback());
    515   get_callback1.WaitForResult();
    516   EXPECT_FALSE(get_callback2.cert_handle());
    517 
    518   scoped_refptr<X509Certificate> cert(
    519       ImportCertFromFile(GetTestCertsDirectory(), kCert1.file_name));
    520   TestSetCallback set_callback;
    521 
    522   cache.SetCertificate(cert->os_cert_handle(), set_callback.callback());
    523   set_callback.WaitForResult();
    524   EXPECT_EQ(kCert1.cache_key, set_callback.key());
    525   EXPECT_EQ(0U, cache.mem_cache_hits_for_testing());
    526 
    527   cache.GetCertificate(kCert1.cache_key, get_callback2.callback());
    528   get_callback2.WaitForResult();
    529   EXPECT_TRUE(X509Certificate::IsSameOSCert(get_callback2.cert_handle(),
    530                                             cert->os_cert_handle()));
    531   EXPECT_EQ(1U, cache.mem_cache_hits_for_testing());
    532   ASSERT_NO_FATAL_FAILURE(CheckCertCached(&backend, kCert1));
    533 }
    534 
    535 }  // namespace net
    536