blob: f3ba0b64df7ddbee786433f152d8a515069c4c8a [file] [log] [blame]
Ben Murdochbb1529c2013-08-08 10:24:53 +01001// Copyright 2013 The Chromium Authors. All rights reserved.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdochbb1529c2013-08-08 10:24:53 +01005#include "content/browser/dom_storage/dom_storage_database.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01006
7#include "base/file_util.h"
8#include "base/files/file_path.h"
9#include "base/files/scoped_temp_dir.h"
10#include "base/path_service.h"
11#include "base/strings/utf_string_conversions.h"
12#include "sql/statement.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010013#include "sql/test/scoped_error_ignorer.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010014#include "testing/gtest/include/gtest/gtest.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010015#include "third_party/sqlite/sqlite3.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010016
Ben Murdochbb1529c2013-08-08 10:24:53 +010017namespace content {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010018
19void CreateV1Table(sql::Connection* db) {
20 ASSERT_TRUE(db->is_open());
21 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
22 ASSERT_TRUE(db->Execute(
23 "CREATE TABLE ItemTable ("
24 "key TEXT UNIQUE ON CONFLICT REPLACE, "
25 "value TEXT NOT NULL ON CONFLICT FAIL)"));
26}
27
28void CreateV2Table(sql::Connection* db) {
29 ASSERT_TRUE(db->is_open());
30 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
31 ASSERT_TRUE(db->Execute(
32 "CREATE TABLE ItemTable ("
33 "key TEXT UNIQUE ON CONFLICT REPLACE, "
34 "value BLOB NOT NULL ON CONFLICT FAIL)"));
35}
36
37void CreateInvalidKeyColumnTable(sql::Connection* db) {
38 // Create a table with the key type as FLOAT - this is "invalid"
39 // as far as the DOM Storage db is concerned.
40 ASSERT_TRUE(db->is_open());
41 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
42 ASSERT_TRUE(db->Execute(
43 "CREATE TABLE IF NOT EXISTS ItemTable ("
44 "key FLOAT UNIQUE ON CONFLICT REPLACE, "
45 "value BLOB NOT NULL ON CONFLICT FAIL)"));
46}
47void CreateInvalidValueColumnTable(sql::Connection* db) {
48 // Create a table with the value type as FLOAT - this is "invalid"
49 // as far as the DOM Storage db is concerned.
50 ASSERT_TRUE(db->is_open());
51 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
52 ASSERT_TRUE(db->Execute(
53 "CREATE TABLE IF NOT EXISTS ItemTable ("
54 "key TEXT UNIQUE ON CONFLICT REPLACE, "
55 "value FLOAT NOT NULL ON CONFLICT FAIL)"));
56}
57
58void InsertDataV1(sql::Connection* db,
59 const base::string16& key,
60 const base::string16& value) {
61 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE,
62 "INSERT INTO ItemTable VALUES (?,?)"));
63 statement.BindString16(0, key);
64 statement.BindString16(1, value);
65 ASSERT_TRUE(statement.is_valid());
66 statement.Run();
67}
68
Ben Murdochbb1529c2013-08-08 10:24:53 +010069void CheckValuesMatch(DOMStorageDatabase* db,
70 const DOMStorageValuesMap& expected) {
71 DOMStorageValuesMap values_read;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010072 db->ReadAllValues(&values_read);
73 EXPECT_EQ(expected.size(), values_read.size());
74
Ben Murdochbb1529c2013-08-08 10:24:53 +010075 DOMStorageValuesMap::const_iterator it = values_read.begin();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010076 for (; it != values_read.end(); ++it) {
77 base::string16 key = it->first;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010078 base::NullableString16 value = it->second;
79 base::NullableString16 expected_value = expected.find(key)->second;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010080 EXPECT_EQ(expected_value.string(), value.string());
81 EXPECT_EQ(expected_value.is_null(), value.is_null());
82 }
83}
84
Ben Murdochbb1529c2013-08-08 10:24:53 +010085void CreateMapWithValues(DOMStorageValuesMap* values) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010086 base::string16 kCannedKeys[] = {
87 ASCIIToUTF16("test"),
88 ASCIIToUTF16("company"),
89 ASCIIToUTF16("date"),
90 ASCIIToUTF16("empty")
91 };
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010092 base::NullableString16 kCannedValues[] = {
93 base::NullableString16(ASCIIToUTF16("123"), false),
94 base::NullableString16(ASCIIToUTF16("Google"), false),
95 base::NullableString16(ASCIIToUTF16("18-01-2012"), false),
96 base::NullableString16(base::string16(), false)
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010097 };
98 for (unsigned i = 0; i < sizeof(kCannedKeys) / sizeof(kCannedKeys[0]); i++)
99 (*values)[kCannedKeys[i]] = kCannedValues[i];
100}
101
Ben Murdochbb1529c2013-08-08 10:24:53 +0100102TEST(DOMStorageDatabaseTest, SimpleOpenAndClose) {
103 DOMStorageDatabase db;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100104 EXPECT_FALSE(db.IsOpen());
105 ASSERT_TRUE(db.LazyOpen(true));
106 EXPECT_TRUE(db.IsOpen());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100107 EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100108 db.Close();
109 EXPECT_FALSE(db.IsOpen());
110}
111
Ben Murdochbb1529c2013-08-08 10:24:53 +0100112TEST(DOMStorageDatabaseTest, CloseEmptyDatabaseDeletesFile) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100113 base::ScopedTempDir temp_dir;
114 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100115 base::FilePath file_name =
Ben Murdochbb1529c2013-08-08 10:24:53 +0100116 temp_dir.path().AppendASCII("TestDOMStorageDatabase.db");
117 DOMStorageValuesMap storage;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100118 CreateMapWithValues(&storage);
119
120 // First test the case that explicitly clearing the database will
121 // trigger its deletion from disk.
122 {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100123 DOMStorageDatabase db(file_name);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100124 EXPECT_EQ(file_name, db.file_path());
125 ASSERT_TRUE(db.CommitChanges(false, storage));
126 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100127 EXPECT_TRUE(base::PathExists(file_name));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100128
129 {
130 // Check that reading an existing db with data in it
131 // keeps the DB on disk on close.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100132 DOMStorageDatabase db(file_name);
133 DOMStorageValuesMap values;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100134 db.ReadAllValues(&values);
135 EXPECT_EQ(storage.size(), values.size());
136 }
137
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100138 EXPECT_TRUE(base::PathExists(file_name));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100139 storage.clear();
140
141 {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100142 DOMStorageDatabase db(file_name);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100143 ASSERT_TRUE(db.CommitChanges(true, storage));
144 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100145 EXPECT_FALSE(base::PathExists(file_name));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100146
147 // Now ensure that a series of updates and removals whose net effect
148 // is an empty database also triggers deletion.
149 CreateMapWithValues(&storage);
150 {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100151 DOMStorageDatabase db(file_name);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100152 ASSERT_TRUE(db.CommitChanges(false, storage));
153 }
154
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100155 EXPECT_TRUE(base::PathExists(file_name));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100156
157 {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100158 DOMStorageDatabase db(file_name);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100159 ASSERT_TRUE(db.CommitChanges(false, storage));
Ben Murdochbb1529c2013-08-08 10:24:53 +0100160 DOMStorageValuesMap::iterator it = storage.begin();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100161 for (; it != storage.end(); ++it)
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100162 it->second = base::NullableString16();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100163 ASSERT_TRUE(db.CommitChanges(false, storage));
164 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100165 EXPECT_FALSE(base::PathExists(file_name));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100166}
167
Ben Murdochbb1529c2013-08-08 10:24:53 +0100168TEST(DOMStorageDatabaseTest, TestLazyOpenIsLazy) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100169 // This test needs to operate with a file on disk to ensure that we will
170 // open a file that already exists when only invoking ReadAllValues.
171 base::ScopedTempDir temp_dir;
172 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100173 base::FilePath file_name =
Ben Murdochbb1529c2013-08-08 10:24:53 +0100174 temp_dir.path().AppendASCII("TestDOMStorageDatabase.db");
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100175
Ben Murdochbb1529c2013-08-08 10:24:53 +0100176 DOMStorageDatabase db(file_name);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100177 EXPECT_FALSE(db.IsOpen());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100178 DOMStorageValuesMap values;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100179 db.ReadAllValues(&values);
180 // Reading an empty db should not open the database.
181 EXPECT_FALSE(db.IsOpen());
182
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100183 values[ASCIIToUTF16("key")] =
184 base::NullableString16(ASCIIToUTF16("value"), false);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100185 db.CommitChanges(false, values);
186 // Writing content should open the database.
187 EXPECT_TRUE(db.IsOpen());
188
189 db.Close();
190 ASSERT_FALSE(db.IsOpen());
191
192 // Reading from an existing database should open the database.
193 CheckValuesMatch(&db, values);
194 EXPECT_TRUE(db.IsOpen());
195}
196
Ben Murdochbb1529c2013-08-08 10:24:53 +0100197TEST(DOMStorageDatabaseTest, TestDetectSchemaVersion) {
198 DOMStorageDatabase db;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100199 db.db_.reset(new sql::Connection());
200 ASSERT_TRUE(db.db_->OpenInMemory());
201
202 CreateInvalidValueColumnTable(db.db_.get());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100203 EXPECT_EQ(DOMStorageDatabase::INVALID, db.DetectSchemaVersion());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100204
205 CreateInvalidKeyColumnTable(db.db_.get());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100206 EXPECT_EQ(DOMStorageDatabase::INVALID, db.DetectSchemaVersion());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100207
208 CreateV1Table(db.db_.get());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100209 EXPECT_EQ(DOMStorageDatabase::V1, db.DetectSchemaVersion());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100210
211 CreateV2Table(db.db_.get());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100212 EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100213}
214
Ben Murdochbb1529c2013-08-08 10:24:53 +0100215TEST(DOMStorageDatabaseTest, TestLazyOpenUpgradesDatabase) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100216 // This test needs to operate with a file on disk so that we
217 // can create a table at version 1 and then close it again
218 // so that LazyOpen sees there is work to do (LazyOpen will return
219 // early if the database is already open).
220 base::ScopedTempDir temp_dir;
221 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100222 base::FilePath file_name =
Ben Murdochbb1529c2013-08-08 10:24:53 +0100223 temp_dir.path().AppendASCII("TestDOMStorageDatabase.db");
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100224
Ben Murdochbb1529c2013-08-08 10:24:53 +0100225 DOMStorageDatabase db(file_name);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100226 db.db_.reset(new sql::Connection());
227 ASSERT_TRUE(db.db_->Open(file_name));
228 CreateV1Table(db.db_.get());
229 db.Close();
230
231 EXPECT_TRUE(db.LazyOpen(true));
Ben Murdochbb1529c2013-08-08 10:24:53 +0100232 EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100233}
234
Ben Murdochbb1529c2013-08-08 10:24:53 +0100235TEST(DOMStorageDatabaseTest, SimpleWriteAndReadBack) {
236 DOMStorageDatabase db;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100237
Ben Murdochbb1529c2013-08-08 10:24:53 +0100238 DOMStorageValuesMap storage;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100239 CreateMapWithValues(&storage);
240
241 EXPECT_TRUE(db.CommitChanges(false, storage));
242 CheckValuesMatch(&db, storage);
243}
244
Ben Murdochbb1529c2013-08-08 10:24:53 +0100245TEST(DOMStorageDatabaseTest, WriteWithClear) {
246 DOMStorageDatabase db;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100247
Ben Murdochbb1529c2013-08-08 10:24:53 +0100248 DOMStorageValuesMap storage;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100249 CreateMapWithValues(&storage);
250
251 ASSERT_TRUE(db.CommitChanges(false, storage));
252 CheckValuesMatch(&db, storage);
253
254 // Insert some values, clearing the database first.
255 storage.clear();
256 storage[ASCIIToUTF16("another_key")] =
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100257 base::NullableString16(ASCIIToUTF16("test"), false);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100258 ASSERT_TRUE(db.CommitChanges(true, storage));
259 CheckValuesMatch(&db, storage);
260
261 // Now clear the values without inserting any new ones.
262 storage.clear();
263 ASSERT_TRUE(db.CommitChanges(true, storage));
264 CheckValuesMatch(&db, storage);
265}
266
Ben Murdochbb1529c2013-08-08 10:24:53 +0100267TEST(DOMStorageDatabaseTest, UpgradeFromV1ToV2WithData) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100268 const base::string16 kCannedKey = ASCIIToUTF16("foo");
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100269 const base::NullableString16 kCannedValue(ASCIIToUTF16("bar"), false);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100270 DOMStorageValuesMap expected;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100271 expected[kCannedKey] = kCannedValue;
272
Ben Murdochbb1529c2013-08-08 10:24:53 +0100273 DOMStorageDatabase db;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100274 db.db_.reset(new sql::Connection());
275 ASSERT_TRUE(db.db_->OpenInMemory());
276 CreateV1Table(db.db_.get());
277 InsertDataV1(db.db_.get(), kCannedKey, kCannedValue.string());
278
279 ASSERT_TRUE(db.UpgradeVersion1To2());
280
Ben Murdochbb1529c2013-08-08 10:24:53 +0100281 EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100282
283 CheckValuesMatch(&db, expected);
284}
285
Ben Murdochbb1529c2013-08-08 10:24:53 +0100286TEST(DOMStorageDatabaseTest, TestSimpleRemoveOneValue) {
287 DOMStorageDatabase db;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100288
289 ASSERT_TRUE(db.LazyOpen(true));
290 const base::string16 kCannedKey = ASCIIToUTF16("test");
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100291 const base::NullableString16 kCannedValue(ASCIIToUTF16("data"), false);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100292 DOMStorageValuesMap expected;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100293 expected[kCannedKey] = kCannedValue;
294
295 // First write some data into the database.
296 ASSERT_TRUE(db.CommitChanges(false, expected));
297 CheckValuesMatch(&db, expected);
298
Ben Murdochbb1529c2013-08-08 10:24:53 +0100299 DOMStorageValuesMap values;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100300 // A null string in the map should mean that that key gets
301 // removed.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100302 values[kCannedKey] = base::NullableString16();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100303 EXPECT_TRUE(db.CommitChanges(false, values));
304
305 expected.clear();
306 CheckValuesMatch(&db, expected);
307}
308
Ben Murdochbb1529c2013-08-08 10:24:53 +0100309TEST(DOMStorageDatabaseTest, TestCanOpenAndReadWebCoreDatabase) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100310 base::FilePath webcore_database;
311 PathService::Get(base::DIR_SOURCE_ROOT, &webcore_database);
312 webcore_database = webcore_database.AppendASCII("webkit");
313 webcore_database = webcore_database.AppendASCII("data");
314 webcore_database = webcore_database.AppendASCII("dom_storage");
315 webcore_database =
316 webcore_database.AppendASCII("webcore_test_database.localstorage");
317
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100318 ASSERT_TRUE(base::PathExists(webcore_database));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100319
Ben Murdochbb1529c2013-08-08 10:24:53 +0100320 DOMStorageDatabase db(webcore_database);
321 DOMStorageValuesMap values;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100322 db.ReadAllValues(&values);
323 EXPECT_TRUE(db.IsOpen());
324 EXPECT_EQ(2u, values.size());
325
Ben Murdochbb1529c2013-08-08 10:24:53 +0100326 DOMStorageValuesMap::const_iterator it =
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100327 values.find(ASCIIToUTF16("value"));
328 EXPECT_TRUE(it != values.end());
329 EXPECT_EQ(ASCIIToUTF16("I am in local storage!"), it->second.string());
330
331 it = values.find(ASCIIToUTF16("timestamp"));
332 EXPECT_TRUE(it != values.end());
333 EXPECT_EQ(ASCIIToUTF16("1326738338841"), it->second.string());
334
335 it = values.find(ASCIIToUTF16("not_there"));
336 EXPECT_TRUE(it == values.end());
337}
338
Ben Murdochbb1529c2013-08-08 10:24:53 +0100339TEST(DOMStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100340 // Write into the temporary file first.
341 base::ScopedTempDir temp_dir;
342 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100343 base::FilePath file_name =
Ben Murdochbb1529c2013-08-08 10:24:53 +0100344 temp_dir.path().AppendASCII("TestDOMStorageDatabase.db");
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100345
346 const char kData[] = "I am not a database.";
347 file_util::WriteFile(file_name, kData, strlen(kData));
348
349 {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100350 sql::ScopedErrorIgnorer ignore_errors;
351 ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ);
352
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100353 // Try and open the file. As it's not a database, we should end up deleting
354 // it and creating a new, valid file, so everything should actually
355 // succeed.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100356 DOMStorageDatabase db(file_name);
357 DOMStorageValuesMap values;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100358 CreateMapWithValues(&values);
359 EXPECT_TRUE(db.CommitChanges(true, values));
360 EXPECT_TRUE(db.CommitChanges(false, values));
361 EXPECT_TRUE(db.IsOpen());
362
363 CheckValuesMatch(&db, values);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100364
365 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100366 }
367
368 {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100369 sql::ScopedErrorIgnorer ignore_errors;
370 ignore_errors.IgnoreError(SQLITE_CANTOPEN);
371
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100372 // Try to open a directory, we should fail gracefully and not attempt
373 // to delete it.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100374 DOMStorageDatabase db(temp_dir.path());
375 DOMStorageValuesMap values;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100376 CreateMapWithValues(&values);
377 EXPECT_FALSE(db.CommitChanges(true, values));
378 EXPECT_FALSE(db.CommitChanges(false, values));
379 EXPECT_FALSE(db.IsOpen());
380
381 values.clear();
382
383 db.ReadAllValues(&values);
384 EXPECT_EQ(0u, values.size());
385 EXPECT_FALSE(db.IsOpen());
386
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100387 EXPECT_TRUE(base::PathExists(temp_dir.path()));
388
389 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100390 }
391}
392
Ben Murdochbb1529c2013-08-08 10:24:53 +0100393} // namespace content