1 // Copyright (c) 2013 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/files/file.h"
8 #include "base/files/file_path.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "content/browser/indexed_db/indexed_db_backing_store.h"
13 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/leveldatabase/env_chromium.h"
17 using base::StringPiece;
18 using content::IndexedDBBackingStore;
19 using content::LevelDBComparator;
20 using content::LevelDBDatabase;
21 using content::LevelDBFactory;
22 using content::LevelDBSnapshot;
29 class IndexedDBFactory;
33 class URLRequestContext;
38 class BustedLevelDBDatabase : public LevelDBDatabase {
40 static scoped_ptr<LevelDBDatabase> Open(
41 const base::FilePath& file_name,
42 const LevelDBComparator* /*comparator*/) {
43 return scoped_ptr<LevelDBDatabase>(new BustedLevelDBDatabase);
45 virtual leveldb::Status Get(const base::StringPiece& key,
48 const LevelDBSnapshot* = 0) OVERRIDE {
49 return leveldb::Status::IOError("It's busted!");
53 class MockLevelDBFactory : public LevelDBFactory {
55 MockLevelDBFactory() : destroy_called_(false) {}
56 virtual leveldb::Status OpenLevelDB(
57 const base::FilePath& file_name,
58 const LevelDBComparator* comparator,
59 scoped_ptr<LevelDBDatabase>* db,
60 bool* is_disk_full = 0) OVERRIDE {
61 *db = BustedLevelDBDatabase::Open(file_name, comparator);
62 return leveldb::Status::OK();
64 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
66 EXPECT_FALSE(destroy_called_);
67 destroy_called_ = true;
68 return leveldb::Status::IOError("error");
70 virtual ~MockLevelDBFactory() { EXPECT_TRUE(destroy_called_); }
76 TEST(IndexedDBIOErrorTest, CleanUpTest) {
77 content::IndexedDBFactory* factory = NULL;
78 const GURL origin("http://localhost:81");
79 base::ScopedTempDir temp_directory;
80 ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
81 const base::FilePath path = temp_directory.path();
82 net::URLRequestContext* request_context = NULL;
83 MockLevelDBFactory mock_leveldb_factory;
84 blink::WebIDBDataLoss data_loss =
85 blink::WebIDBDataLossNone;
86 std::string data_loss_message;
87 bool disk_full = false;
88 base::TaskRunner* task_runner = NULL;
89 bool clean_journal = false;
90 scoped_refptr<IndexedDBBackingStore> backing_store =
91 IndexedDBBackingStore::Open(factory,
98 &mock_leveldb_factory,
103 // TODO(dgrogan): Remove expect_destroy if we end up not using it again. It is
104 // currently set to false in all 4 calls below.
106 class MockErrorLevelDBFactory : public LevelDBFactory {
108 MockErrorLevelDBFactory(T error, bool expect_destroy)
110 expect_destroy_(expect_destroy),
111 destroy_called_(false) {}
112 virtual leveldb::Status OpenLevelDB(
113 const base::FilePath& file_name,
114 const LevelDBComparator* comparator,
115 scoped_ptr<LevelDBDatabase>* db,
116 bool* is_disk_full = 0) OVERRIDE {
118 "some filename", "some message", leveldb_env::kNewLogger, error_);
120 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
122 EXPECT_FALSE(destroy_called_);
123 destroy_called_ = true;
124 return leveldb::Status::IOError("error");
126 virtual ~MockErrorLevelDBFactory() {
127 EXPECT_EQ(expect_destroy_, destroy_called_);
132 bool expect_destroy_;
133 bool destroy_called_;
136 TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
137 content::IndexedDBFactory* factory = NULL;
138 const GURL origin("http://localhost:81");
139 net::URLRequestContext* request_context = NULL;
140 base::ScopedTempDir temp_directory;
141 ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
142 const base::FilePath path = temp_directory.path();
143 blink::WebIDBDataLoss data_loss =
144 blink::WebIDBDataLossNone;
145 std::string data_loss_reason;
146 bool disk_full = false;
147 base::TaskRunner* task_runner = NULL;
148 bool clean_journal = false;
150 MockErrorLevelDBFactory<int> mock_leveldb_factory(ENOSPC, false);
151 scoped_refptr<IndexedDBBackingStore> backing_store =
152 IndexedDBBackingStore::Open(factory,
159 &mock_leveldb_factory,
163 MockErrorLevelDBFactory<base::File::Error> mock_leveldb_factory2(
164 base::File::FILE_ERROR_NO_MEMORY, false);
165 scoped_refptr<IndexedDBBackingStore> backing_store2 =
166 IndexedDBBackingStore::Open(factory,
173 &mock_leveldb_factory2,
177 MockErrorLevelDBFactory<int> mock_leveldb_factory3(EIO, false);
178 scoped_refptr<IndexedDBBackingStore> backing_store3 =
179 IndexedDBBackingStore::Open(factory,
186 &mock_leveldb_factory3,
190 MockErrorLevelDBFactory<base::File::Error> mock_leveldb_factory4(
191 base::File::FILE_ERROR_FAILED, false);
192 scoped_refptr<IndexedDBBackingStore> backing_store4 =
193 IndexedDBBackingStore::Open(factory,
200 &mock_leveldb_factory4,