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.
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"
18 class MockIDBFactory
: public IndexedDBFactory
{
20 MockIDBFactory() : IndexedDBFactory(NULL
), duplicate_calls_(false) {}
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;
28 origins_
.insert(origin_url
);
31 if (!origins_
.count(origin_url
)) {
32 duplicate_calls_
= true;
34 origins_
.erase(origin_url
);
39 bool CheckNoOriginsInUse() const {
40 return !duplicate_calls_
&& !origins_
.size();
42 bool CheckSingleOriginInUse(const GURL
& origin
) const {
43 return !duplicate_calls_
&& origins_
.size() == 1 && origins_
.count(origin
);
47 virtual ~MockIDBFactory() {}
50 std::set
<GURL
> origins_
;
51 bool duplicate_calls_
;
54 class MockIDBBackingStore
: public IndexedDBFakeBackingStore
{
56 MockIDBBackingStore(IndexedDBFactory
* factory
, base::TaskRunner
* task_runner
)
57 : IndexedDBFakeBackingStore(factory
, task_runner
),
58 duplicate_calls_(false) {}
60 virtual void ReportBlobUnused(int64 database_id
, int64 blob_key
) OVERRIDE
{
61 unused_blobs_
.insert(std::make_pair(database_id
, blob_key
));
64 typedef std::pair
<int64
, int64
> KeyPair
;
65 typedef std::set
<KeyPair
> KeyPairSet
;
66 bool CheckUnusedBlobsEmpty() const {
67 return !duplicate_calls_
&& !unused_blobs_
.size();
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
));
74 const KeyPairSet
& unused_blobs() const { return unused_blobs_
; }
77 virtual ~MockIDBBackingStore() {}
80 KeyPairSet unused_blobs_
;
81 bool duplicate_calls_
;
84 // Base class for our test fixtures.
85 class IndexedDBActiveBlobRegistryTest
: public testing::Test
{
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())) {}
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(); }
98 static const int64 kDatabaseId0
= 7;
99 static const int64 kDatabaseId1
= 12;
100 static const int64 kBlobKey0
= 77;
101 static const int64 kBlobKey1
= 14;
103 typedef webkit_blob::ShareableFileReference::FinalReleaseCallback
107 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
108 scoped_refptr
<MockIDBFactory
> factory_
;
109 scoped_refptr
<MockIDBBackingStore
> backing_store_
;
110 scoped_ptr
<IndexedDBActiveBlobRegistry
> registry_
;
112 DISALLOW_COPY_AND_ASSIGN(IndexedDBActiveBlobRegistryTest
);
115 TEST_F(IndexedDBActiveBlobRegistryTest
, DeleteUnused
) {
116 EXPECT_TRUE(factory()->CheckNoOriginsInUse());
117 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
119 EXPECT_FALSE(registry()->MarkDeletedCheckIfUsed(kDatabaseId0
, kBlobKey0
));
122 EXPECT_TRUE(factory()->CheckNoOriginsInUse());
123 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
126 TEST_F(IndexedDBActiveBlobRegistryTest
, SimpleUse
) {
127 EXPECT_TRUE(factory()->CheckNoOriginsInUse());
128 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
130 base::Closure add_ref
=
131 registry()->GetAddBlobRefCallback(kDatabaseId0
, kBlobKey0
);
132 ReleaseCallback release
=
133 registry()->GetFinalReleaseCallback(kDatabaseId0
, kBlobKey0
);
137 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
138 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
140 release
.Run(base::FilePath());
143 EXPECT_TRUE(factory()->CheckNoOriginsInUse());
144 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
147 TEST_F(IndexedDBActiveBlobRegistryTest
, DeleteWhileInUse
) {
148 EXPECT_TRUE(factory()->CheckNoOriginsInUse());
149 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
151 base::Closure add_ref
=
152 registry()->GetAddBlobRefCallback(kDatabaseId0
, kBlobKey0
);
153 ReleaseCallback release
=
154 registry()->GetFinalReleaseCallback(kDatabaseId0
, kBlobKey0
);
159 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
160 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
162 EXPECT_TRUE(registry()->MarkDeletedCheckIfUsed(kDatabaseId0
, kBlobKey0
));
165 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
166 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
168 release
.Run(base::FilePath());
171 EXPECT_TRUE(factory()->CheckNoOriginsInUse());
172 EXPECT_TRUE(backing_store()->CheckSingleUnusedBlob(kDatabaseId0
, kBlobKey0
));
175 TEST_F(IndexedDBActiveBlobRegistryTest
, MultipleBlobs
) {
176 EXPECT_TRUE(factory()->CheckNoOriginsInUse());
177 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
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
);
200 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
201 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
203 release_00
.Run(base::FilePath());
208 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
209 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
211 EXPECT_TRUE(registry()->MarkDeletedCheckIfUsed(kDatabaseId0
, kBlobKey1
));
214 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
215 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
217 release_01
.Run(base::FilePath());
218 release_11
.Run(base::FilePath());
221 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
222 EXPECT_TRUE(backing_store()->CheckSingleUnusedBlob(kDatabaseId0
, kBlobKey1
));
224 release_10
.Run(base::FilePath());
227 EXPECT_TRUE(factory()->CheckNoOriginsInUse());
228 EXPECT_TRUE(backing_store()->CheckSingleUnusedBlob(kDatabaseId0
, kBlobKey1
));
231 TEST_F(IndexedDBActiveBlobRegistryTest
, ForceShutdown
) {
232 EXPECT_TRUE(factory()->CheckNoOriginsInUse());
233 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
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
);
247 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
248 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
250 registry()->ForceShutdown();
256 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
257 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
259 release_0
.Run(base::FilePath());
260 release_1
.Run(base::FilePath());
264 EXPECT_TRUE(factory()->CheckSingleOriginInUse(backing_store()->origin_url()));
265 EXPECT_TRUE(backing_store()->CheckUnusedBlobsEmpty());
270 } // namespace content