Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_unittest.cc
bloba3d2fb6fa00c9b71836ed1f8aecc294c49e43584
1 // Copyright (c) 2012 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.
5 #include "base/file_util.h"
6 #include "base/files/scoped_temp_dir.h"
7 #include "base/test/test_simple_task_runner.h"
8 #include "base/threading/thread.h"
9 #include "content/browser/browser_thread_impl.h"
10 #include "content/browser/indexed_db/indexed_db_connection.h"
11 #include "content/browser/indexed_db/indexed_db_context_impl.h"
12 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
13 #include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
14 #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
15 #include "content/public/browser/storage_partition.h"
16 #include "content/public/common/url_constants.h"
17 #include "content/public/test/mock_special_storage_policy.h"
18 #include "content/public/test/test_browser_context.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "webkit/browser/quota/quota_manager.h"
21 #include "webkit/browser/quota/special_storage_policy.h"
22 #include "webkit/common/database/database_identifier.h"
24 namespace content {
26 class IndexedDBTest : public testing::Test {
27 public:
28 const GURL kNormalOrigin;
29 const GURL kSessionOnlyOrigin;
31 IndexedDBTest()
32 : kNormalOrigin("http://normal/"),
33 kSessionOnlyOrigin("http://session-only/"),
34 task_runner_(new base::TestSimpleTaskRunner),
35 special_storage_policy_(new MockSpecialStoragePolicy),
36 file_thread_(BrowserThread::FILE_USER_BLOCKING, &message_loop_),
37 io_thread_(BrowserThread::IO, &message_loop_) {
38 special_storage_policy_->AddSessionOnly(kSessionOnlyOrigin);
41 protected:
42 void FlushIndexedDBTaskRunner() { task_runner_->RunUntilIdle(); }
44 base::MessageLoopForIO message_loop_;
45 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
46 scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
48 private:
49 BrowserThreadImpl file_thread_;
50 BrowserThreadImpl io_thread_;
52 DISALLOW_COPY_AND_ASSIGN(IndexedDBTest);
55 TEST_F(IndexedDBTest, ClearSessionOnlyDatabases) {
56 base::ScopedTempDir temp_dir;
57 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
59 base::FilePath normal_path;
60 base::FilePath session_only_path;
62 // Create the scope which will ensure we run the destructor of the context
63 // which should trigger the clean up.
65 scoped_refptr<IndexedDBContextImpl> idb_context =
66 new IndexedDBContextImpl(temp_dir.path(),
67 special_storage_policy_.get(),
68 NULL,
69 task_runner_.get());
71 normal_path = idb_context->GetFilePathForTesting(
72 storage::GetIdentifierFromOrigin(kNormalOrigin));
73 session_only_path = idb_context->GetFilePathForTesting(
74 storage::GetIdentifierFromOrigin(kSessionOnlyOrigin));
75 ASSERT_TRUE(base::CreateDirectory(normal_path));
76 ASSERT_TRUE(base::CreateDirectory(session_only_path));
77 FlushIndexedDBTaskRunner();
78 message_loop_.RunUntilIdle();
81 FlushIndexedDBTaskRunner();
82 message_loop_.RunUntilIdle();
84 EXPECT_TRUE(base::DirectoryExists(normal_path));
85 EXPECT_FALSE(base::DirectoryExists(session_only_path));
88 TEST_F(IndexedDBTest, SetForceKeepSessionState) {
89 base::ScopedTempDir temp_dir;
90 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
92 base::FilePath normal_path;
93 base::FilePath session_only_path;
95 // Create the scope which will ensure we run the destructor of the context.
97 // Create some indexedDB paths.
98 // With the levelDB backend, these are directories.
99 scoped_refptr<IndexedDBContextImpl> idb_context =
100 new IndexedDBContextImpl(temp_dir.path(),
101 special_storage_policy_.get(),
102 NULL,
103 task_runner_.get());
105 // Save session state. This should bypass the destruction-time deletion.
106 idb_context->SetForceKeepSessionState();
108 normal_path = idb_context->GetFilePathForTesting(
109 storage::GetIdentifierFromOrigin(kNormalOrigin));
110 session_only_path = idb_context->GetFilePathForTesting(
111 storage::GetIdentifierFromOrigin(kSessionOnlyOrigin));
112 ASSERT_TRUE(base::CreateDirectory(normal_path));
113 ASSERT_TRUE(base::CreateDirectory(session_only_path));
114 message_loop_.RunUntilIdle();
117 // Make sure we wait until the destructor has run.
118 message_loop_.RunUntilIdle();
120 // No data was cleared because of SetForceKeepSessionState.
121 EXPECT_TRUE(base::DirectoryExists(normal_path));
122 EXPECT_TRUE(base::DirectoryExists(session_only_path));
125 class ForceCloseDBCallbacks : public IndexedDBCallbacks {
126 public:
127 ForceCloseDBCallbacks(scoped_refptr<IndexedDBContextImpl> idb_context,
128 const GURL& origin_url)
129 : IndexedDBCallbacks(NULL, 0, 0),
130 idb_context_(idb_context),
131 origin_url_(origin_url) {}
133 virtual void OnSuccess() OVERRIDE {}
134 virtual void OnSuccess(const std::vector<base::string16>&) OVERRIDE {}
135 virtual void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
136 const IndexedDBDatabaseMetadata& metadata) OVERRIDE {
137 connection_ = connection.Pass();
138 idb_context_->ConnectionOpened(origin_url_, connection_.get());
141 IndexedDBConnection* connection() { return connection_.get(); }
143 protected:
144 virtual ~ForceCloseDBCallbacks() {}
146 private:
147 scoped_refptr<IndexedDBContextImpl> idb_context_;
148 GURL origin_url_;
149 scoped_ptr<IndexedDBConnection> connection_;
150 DISALLOW_COPY_AND_ASSIGN(ForceCloseDBCallbacks);
153 TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
154 base::ScopedTempDir temp_dir;
155 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
157 scoped_refptr<MockIndexedDBDatabaseCallbacks> open_db_callbacks(
158 new MockIndexedDBDatabaseCallbacks());
159 scoped_refptr<MockIndexedDBDatabaseCallbacks> closed_db_callbacks(
160 new MockIndexedDBDatabaseCallbacks());
162 base::FilePath test_path;
164 // Create the scope which will ensure we run the destructor of the context.
166 TestBrowserContext browser_context;
168 const GURL kTestOrigin("http://test/");
170 scoped_refptr<IndexedDBContextImpl> idb_context =
171 new IndexedDBContextImpl(temp_dir.path(),
172 special_storage_policy_.get(),
173 NULL,
174 task_runner_.get());
176 scoped_refptr<ForceCloseDBCallbacks> open_callbacks =
177 new ForceCloseDBCallbacks(idb_context, kTestOrigin);
179 scoped_refptr<ForceCloseDBCallbacks> closed_callbacks =
180 new ForceCloseDBCallbacks(idb_context, kTestOrigin);
182 IndexedDBFactory* factory = idb_context->GetIDBFactory();
184 test_path = idb_context->GetFilePathForTesting(
185 storage::GetIdentifierFromOrigin(kTestOrigin));
187 IndexedDBPendingConnection open_connection(open_callbacks,
188 open_db_callbacks,
189 0 /* child_process_id */,
190 0 /* host_transaction_id */,
191 0 /* version */);
192 factory->Open(base::ASCIIToUTF16("opendb"),
193 open_connection,
194 NULL /* request_context */,
195 kTestOrigin,
196 idb_context->data_path());
197 IndexedDBPendingConnection closed_connection(closed_callbacks,
198 closed_db_callbacks,
199 0 /* child_process_id */,
200 0 /* host_transaction_id */,
201 0 /* version */);
202 factory->Open(base::ASCIIToUTF16("closeddb"),
203 closed_connection,
204 NULL /* request_context */,
205 kTestOrigin,
206 idb_context->data_path());
208 closed_callbacks->connection()->Close();
210 idb_context->TaskRunner()->PostTask(
211 FROM_HERE,
212 base::Bind(
213 &IndexedDBContextImpl::DeleteForOrigin, idb_context, kTestOrigin));
214 FlushIndexedDBTaskRunner();
215 message_loop_.RunUntilIdle();
218 // Make sure we wait until the destructor has run.
219 message_loop_.RunUntilIdle();
221 EXPECT_TRUE(open_db_callbacks->forced_close_called());
222 EXPECT_FALSE(closed_db_callbacks->forced_close_called());
223 EXPECT_FALSE(base::DirectoryExists(test_path));
226 TEST_F(IndexedDBTest, DeleteFailsIfDirectoryLocked) {
227 base::ScopedTempDir temp_dir;
228 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
229 const GURL kTestOrigin("http://test/");
231 scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
232 temp_dir.path(), special_storage_policy_.get(), NULL, task_runner_.get());
234 base::FilePath test_path = idb_context->GetFilePathForTesting(
235 storage::GetIdentifierFromOrigin(kTestOrigin));
236 ASSERT_TRUE(base::CreateDirectory(test_path));
238 scoped_ptr<LevelDBLock> lock =
239 LevelDBDatabase::LockForTesting(test_path);
240 ASSERT_TRUE(lock);
242 idb_context->TaskRunner()->PostTask(
243 FROM_HERE,
244 base::Bind(
245 &IndexedDBContextImpl::DeleteForOrigin, idb_context, kTestOrigin));
246 FlushIndexedDBTaskRunner();
248 EXPECT_TRUE(base::DirectoryExists(test_path));
251 TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnCommitFailure) {
252 const GURL kTestOrigin("http://test/");
254 base::ScopedTempDir temp_dir;
255 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
257 scoped_refptr<IndexedDBContextImpl> context = new IndexedDBContextImpl(
258 temp_dir.path(), special_storage_policy_.get(), NULL, task_runner_.get());
260 scoped_refptr<IndexedDBFactoryImpl> factory =
261 static_cast<IndexedDBFactoryImpl*>(context->GetIDBFactory());
263 scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks());
264 scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
265 new MockIndexedDBDatabaseCallbacks());
266 const int64 transaction_id = 1;
267 IndexedDBPendingConnection connection(
268 callbacks,
269 db_callbacks,
270 0 /* child_process_id */,
271 transaction_id,
272 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
273 factory->Open(base::ASCIIToUTF16("db"),
274 connection,
275 NULL /* request_context */,
276 kTestOrigin,
277 temp_dir.path());
279 EXPECT_TRUE(callbacks->connection());
281 // ConnectionOpened() is usually called by the dispatcher.
282 context->ConnectionOpened(kTestOrigin, callbacks->connection());
284 EXPECT_TRUE(factory->IsBackingStoreOpen(kTestOrigin));
286 // Simulate the write failure.
287 leveldb::Status status = leveldb::Status::IOError("Simulated failure");
288 callbacks->connection()->database()->TransactionCommitFailed(status);
290 EXPECT_TRUE(db_callbacks->forced_close_called());
291 EXPECT_FALSE(factory->IsBackingStoreOpen(kTestOrigin));
294 } // namespace content