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