Home | History | Annotate | Download | only in indexed_db
      1 // Copyright 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 <set>
      6 
      7 #include "base/test/test_simple_task_runner.h"
      8 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
      9 #include "content/browser/indexed_db/indexed_db_backing_store.h"
     10 #include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
     11 #include "content/browser/indexed_db/mock_indexed_db_factory.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 namespace content {
     15 
     16 namespace {
     17 
     18 class RegistryTestMockFactory : public MockIndexedDBFactory {
     19  public:
     20   RegistryTestMockFactory() : duplicate_calls_(false) {}
     21 
     22   virtual void ReportOutstandingBlobs(const GURL& origin_url,
     23                                       bool blobs_outstanding) OVERRIDE {
     24     if (blobs_outstanding) {
     25       if (origins_.count(origin_url)) {
     26         duplicate_calls_ = true;
     27       } else {
     28         origins_.insert(origin_url);
     29       }
     30     } else {
     31       if (!origins_.count(origin_url)) {
     32         duplicate_calls_ = true;
     33       } else {
     34         origins_.erase(origin_url);
     35       }
     36     }
     37   }
     38 
     39   bool CheckNoOriginsInUse() const {
     40     return !duplicate_calls_ && !origins_.size();
     41   }
     42 
     43   bool CheckSingleOriginInUse(const GURL& origin) const {
     44     return !duplicate_calls_ && origins_.size() == 1 && origins_.count(origin);
     45   }
     46 
     47  private:
     48   virtual ~RegistryTestMockFactory() {}
     49 
     50   std::set<GURL> origins_;
     51   bool duplicate_calls_;
     52 
     53   DISALLOW_COPY_AND_ASSIGN(RegistryTestMockFactory);
     54 };
     55 
     56 class MockIDBBackingStore : public IndexedDBFakeBackingStore {
     57  public:
     58   typedef std::pair<int64, int64> KeyPair;
     59   typedef std::set<KeyPair> KeyPairSet;
     60 
     61   MockIDBBackingStore(IndexedDBFactory* factory,
     62                       base::SequencedTaskRunner* task_runner)
     63       : IndexedDBFakeBackingStore(factory, task_runner),
     64         duplicate_calls_(false) {}
     65 
     66   virtual void ReportBlobUnused(int64 database_id, int64 blob_key) OVERRIDE {
     67     unused_blobs_.insert(std::make_pair(database_id, blob_key));
     68   }
     69 
     70   bool CheckUnusedBlobsEmpty() const {
     71     return !duplicate_calls_ && !unused_blobs_.size();
     72   }
     73   bool CheckSingleUnusedBlob(int64 database_id, int64 blob_key) const {
     74     return !duplicate_calls_ && unused_blobs_.size() == 1 &&
     75            unused_blobs_.count(std::make_pair(database_id, blob_key));
     76   }
     77 
     78   const KeyPairSet& unused_blobs() const { return unused_blobs_; }
     79 
     80  protected:
     81   virtual ~MockIDBBackingStore() {}
     82 
     83  private:
     84   KeyPairSet unused_blobs_;
     85   bool duplicate_calls_;
     86 
     87   DISALLOW_COPY_AND_ASSIGN(MockIDBBackingStore);
     88 };
     89 
     90 // Base class for our test fixtures.
     91 class IndexedDBActiveBlobRegistryTest : public testing::Test {
     92  public:
     93   typedef storage::ShareableFileReference::FinalReleaseCallback
     94       ReleaseCallback;
     95 
     96   static const int64 kDatabaseId0 = 7;
     97   static const int64 kDatabaseId1 = 12;
     98   static const int64 kBlobKey0 = 77;
     99   static const int64 kBlobKey1 = 14;
    100 
    101   IndexedDBActiveBlobRegistryTest()
    102       : task_runner_(new base::TestSimpleTaskRunner),
    103         factory_(new RegistryTestMockFactory),
    104         backing_store_(
    105             new MockIDBBackingStore(factory_.get(), task_runner_.get())),
    106         registry_(new IndexedDBActiveBlobRegistry(backing_store_.get())) {}
    107 
    108   void RunUntilIdle() { task_runner_->RunUntilIdle(); }
    109   RegistryTestMockFactory* factory() const { return factory_.get(); }
    110   MockIDBBackingStore* backing_store() const { return backing_store_.get(); }
    111   IndexedDBActiveBlobRegistry* registry() const { return registry_.get(); }
    112 
    113  private:
    114   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
    115   scoped_refptr<RegistryTestMockFactory> factory_;
    116   scoped_refptr<MockIDBBackingStore> backing_store_;
    117   scoped_ptr<IndexedDBActiveBlobRegistry> registry_;
    118 
    119   DISALLOW_COPY_AND_ASSIGN(IndexedDBActiveBlobRegistryTest);
    120 };
    121 
    122 TEST_F(IndexedDBActiveBlobRegistryTest, DeleteUnused) {
    123   EXPECT_TRUE(factory()->CheckNoOriginsInUse());
    124   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    125 
    126   EXPECT_FALSE(registry()->MarkDeletedCheckIfUsed(kDatabaseId0, kBlobKey0));
    127   RunUntilIdle();
    128 
    129   EXPECT_TRUE(factory()->CheckNoOriginsInUse());
    130   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    131 }
    132 
    133 TEST_F(IndexedDBActiveBlobRegistryTest, SimpleUse) {
    134   EXPECT_TRUE(factory()->CheckNoOriginsInUse());
    135   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    136 
    137   base::Closure add_ref =
    138       registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey0);
    139   ReleaseCallback release =
    140       registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey0);
    141   add_ref.Run();
    142   RunUntilIdle();
    143 
    144   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    145   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    146 
    147   release.Run(base::FilePath());
    148   RunUntilIdle();
    149 
    150   EXPECT_TRUE(factory()->CheckNoOriginsInUse());
    151   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    152 }
    153 
    154 TEST_F(IndexedDBActiveBlobRegistryTest, DeleteWhileInUse) {
    155   EXPECT_TRUE(factory()->CheckNoOriginsInUse());
    156   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    157 
    158   base::Closure add_ref =
    159       registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey0);
    160   ReleaseCallback release =
    161       registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey0);
    162 
    163   add_ref.Run();
    164   RunUntilIdle();
    165 
    166   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    167   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    168 
    169   EXPECT_TRUE(registry()->MarkDeletedCheckIfUsed(kDatabaseId0, kBlobKey0));
    170   RunUntilIdle();
    171 
    172   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    173   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    174 
    175   release.Run(base::FilePath());
    176   RunUntilIdle();
    177 
    178   EXPECT_TRUE(factory()->CheckNoOriginsInUse());
    179   EXPECT_TRUE(backing_store()->CheckSingleUnusedBlob(kDatabaseId0, kBlobKey0));
    180 }
    181 
    182 TEST_F(IndexedDBActiveBlobRegistryTest, MultipleBlobs) {
    183   EXPECT_TRUE(factory()->CheckNoOriginsInUse());
    184   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    185 
    186   base::Closure add_ref_00 =
    187       registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey0);
    188   ReleaseCallback release_00 =
    189       registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey0);
    190   base::Closure add_ref_01 =
    191       registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey1);
    192   ReleaseCallback release_01 =
    193       registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey1);
    194   base::Closure add_ref_10 =
    195       registry()->GetAddBlobRefCallback(kDatabaseId1, kBlobKey0);
    196   ReleaseCallback release_10 =
    197       registry()->GetFinalReleaseCallback(kDatabaseId1, kBlobKey0);
    198   base::Closure add_ref_11 =
    199       registry()->GetAddBlobRefCallback(kDatabaseId1, kBlobKey1);
    200   ReleaseCallback release_11 =
    201       registry()->GetFinalReleaseCallback(kDatabaseId1, kBlobKey1);
    202 
    203   add_ref_00.Run();
    204   add_ref_01.Run();
    205   RunUntilIdle();
    206 
    207   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    208   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    209 
    210   release_00.Run(base::FilePath());
    211   add_ref_10.Run();
    212   add_ref_11.Run();
    213   RunUntilIdle();
    214 
    215   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    216   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    217 
    218   EXPECT_TRUE(registry()->MarkDeletedCheckIfUsed(kDatabaseId0, kBlobKey1));
    219   RunUntilIdle();
    220 
    221   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    222   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    223 
    224   release_01.Run(base::FilePath());
    225   release_11.Run(base::FilePath());
    226   RunUntilIdle();
    227 
    228   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    229   EXPECT_TRUE(backing_store()->CheckSingleUnusedBlob(kDatabaseId0, kBlobKey1));
    230 
    231   release_10.Run(base::FilePath());
    232   RunUntilIdle();
    233 
    234   EXPECT_TRUE(factory()->CheckNoOriginsInUse());
    235   EXPECT_TRUE(backing_store()->CheckSingleUnusedBlob(kDatabaseId0, kBlobKey1));
    236 }
    237 
    238 TEST_F(IndexedDBActiveBlobRegistryTest, ForceShutdown) {
    239   EXPECT_TRUE(factory()->CheckNoOriginsInUse());
    240   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    241 
    242   base::Closure add_ref_0 =
    243       registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey0);
    244   ReleaseCallback release_0 =
    245       registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey0);
    246   base::Closure add_ref_1 =
    247       registry()->GetAddBlobRefCallback(kDatabaseId0, kBlobKey1);
    248   ReleaseCallback release_1 =
    249       registry()->GetFinalReleaseCallback(kDatabaseId0, kBlobKey1);
    250 
    251   add_ref_0.Run();
    252   RunUntilIdle();
    253 
    254   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    255   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    256 
    257   registry()->ForceShutdown();
    258 
    259   add_ref_1.Run();
    260   RunUntilIdle();
    261 
    262   // Nothing changes.
    263   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    264   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    265 
    266   release_0.Run(base::FilePath());
    267   release_1.Run(base::FilePath());
    268   RunUntilIdle();
    269 
    270   // Nothing changes.
    271   EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
    272   EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
    273 }
    274 
    275 }  // namespace
    276 
    277 }  // namespace content
    278