Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 1 | // Copyright 2013 The Chromium Authors. All rights reserved. |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 5 | #include "content/browser/dom_storage/dom_storage_database.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 6 | |
| 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 Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 13 | #include "sql/test/scoped_error_ignorer.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 14 | #include "testing/gtest/include/gtest/gtest.h" |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 15 | #include "third_party/sqlite/sqlite3.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 16 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 17 | namespace content { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 18 | |
| 19 | void 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 | |
| 28 | void 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 | |
| 37 | void 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 | } |
| 47 | void 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 | |
| 58 | void 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 Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 69 | void CheckValuesMatch(DOMStorageDatabase* db, |
| 70 | const DOMStorageValuesMap& expected) { |
| 71 | DOMStorageValuesMap values_read; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 72 | db->ReadAllValues(&values_read); |
| 73 | EXPECT_EQ(expected.size(), values_read.size()); |
| 74 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 75 | DOMStorageValuesMap::const_iterator it = values_read.begin(); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 76 | for (; it != values_read.end(); ++it) { |
| 77 | base::string16 key = it->first; |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 78 | base::NullableString16 value = it->second; |
| 79 | base::NullableString16 expected_value = expected.find(key)->second; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 80 | EXPECT_EQ(expected_value.string(), value.string()); |
| 81 | EXPECT_EQ(expected_value.is_null(), value.is_null()); |
| 82 | } |
| 83 | } |
| 84 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 85 | void CreateMapWithValues(DOMStorageValuesMap* values) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 86 | base::string16 kCannedKeys[] = { |
| 87 | ASCIIToUTF16("test"), |
| 88 | ASCIIToUTF16("company"), |
| 89 | ASCIIToUTF16("date"), |
| 90 | ASCIIToUTF16("empty") |
| 91 | }; |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 92 | 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) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 97 | }; |
| 98 | for (unsigned i = 0; i < sizeof(kCannedKeys) / sizeof(kCannedKeys[0]); i++) |
| 99 | (*values)[kCannedKeys[i]] = kCannedValues[i]; |
| 100 | } |
| 101 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 102 | TEST(DOMStorageDatabaseTest, SimpleOpenAndClose) { |
| 103 | DOMStorageDatabase db; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 104 | EXPECT_FALSE(db.IsOpen()); |
| 105 | ASSERT_TRUE(db.LazyOpen(true)); |
| 106 | EXPECT_TRUE(db.IsOpen()); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 107 | EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 108 | db.Close(); |
| 109 | EXPECT_FALSE(db.IsOpen()); |
| 110 | } |
| 111 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 112 | TEST(DOMStorageDatabaseTest, CloseEmptyDatabaseDeletesFile) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 113 | base::ScopedTempDir temp_dir; |
| 114 | ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 115 | base::FilePath file_name = |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 116 | temp_dir.path().AppendASCII("TestDOMStorageDatabase.db"); |
| 117 | DOMStorageValuesMap storage; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 118 | CreateMapWithValues(&storage); |
| 119 | |
| 120 | // First test the case that explicitly clearing the database will |
| 121 | // trigger its deletion from disk. |
| 122 | { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 123 | DOMStorageDatabase db(file_name); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 124 | EXPECT_EQ(file_name, db.file_path()); |
| 125 | ASSERT_TRUE(db.CommitChanges(false, storage)); |
| 126 | } |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 127 | EXPECT_TRUE(base::PathExists(file_name)); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 128 | |
| 129 | { |
| 130 | // Check that reading an existing db with data in it |
| 131 | // keeps the DB on disk on close. |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 132 | DOMStorageDatabase db(file_name); |
| 133 | DOMStorageValuesMap values; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 134 | db.ReadAllValues(&values); |
| 135 | EXPECT_EQ(storage.size(), values.size()); |
| 136 | } |
| 137 | |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 138 | EXPECT_TRUE(base::PathExists(file_name)); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 139 | storage.clear(); |
| 140 | |
| 141 | { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 142 | DOMStorageDatabase db(file_name); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 143 | ASSERT_TRUE(db.CommitChanges(true, storage)); |
| 144 | } |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 145 | EXPECT_FALSE(base::PathExists(file_name)); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 146 | |
| 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 Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 151 | DOMStorageDatabase db(file_name); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 152 | ASSERT_TRUE(db.CommitChanges(false, storage)); |
| 153 | } |
| 154 | |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 155 | EXPECT_TRUE(base::PathExists(file_name)); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 156 | |
| 157 | { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 158 | DOMStorageDatabase db(file_name); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 159 | ASSERT_TRUE(db.CommitChanges(false, storage)); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 160 | DOMStorageValuesMap::iterator it = storage.begin(); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 161 | for (; it != storage.end(); ++it) |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 162 | it->second = base::NullableString16(); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 163 | ASSERT_TRUE(db.CommitChanges(false, storage)); |
| 164 | } |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 165 | EXPECT_FALSE(base::PathExists(file_name)); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 166 | } |
| 167 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 168 | TEST(DOMStorageDatabaseTest, TestLazyOpenIsLazy) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 169 | // 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) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 173 | base::FilePath file_name = |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 174 | temp_dir.path().AppendASCII("TestDOMStorageDatabase.db"); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 175 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 176 | DOMStorageDatabase db(file_name); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 177 | EXPECT_FALSE(db.IsOpen()); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 178 | DOMStorageValuesMap values; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 179 | db.ReadAllValues(&values); |
| 180 | // Reading an empty db should not open the database. |
| 181 | EXPECT_FALSE(db.IsOpen()); |
| 182 | |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 183 | values[ASCIIToUTF16("key")] = |
| 184 | base::NullableString16(ASCIIToUTF16("value"), false); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 185 | 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 Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 197 | TEST(DOMStorageDatabaseTest, TestDetectSchemaVersion) { |
| 198 | DOMStorageDatabase db; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 199 | db.db_.reset(new sql::Connection()); |
| 200 | ASSERT_TRUE(db.db_->OpenInMemory()); |
| 201 | |
| 202 | CreateInvalidValueColumnTable(db.db_.get()); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 203 | EXPECT_EQ(DOMStorageDatabase::INVALID, db.DetectSchemaVersion()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 204 | |
| 205 | CreateInvalidKeyColumnTable(db.db_.get()); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 206 | EXPECT_EQ(DOMStorageDatabase::INVALID, db.DetectSchemaVersion()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 207 | |
| 208 | CreateV1Table(db.db_.get()); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 209 | EXPECT_EQ(DOMStorageDatabase::V1, db.DetectSchemaVersion()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 210 | |
| 211 | CreateV2Table(db.db_.get()); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 212 | EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 213 | } |
| 214 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 215 | TEST(DOMStorageDatabaseTest, TestLazyOpenUpgradesDatabase) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 216 | // 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) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 222 | base::FilePath file_name = |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 223 | temp_dir.path().AppendASCII("TestDOMStorageDatabase.db"); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 224 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 225 | DOMStorageDatabase db(file_name); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 226 | 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 Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 232 | EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 233 | } |
| 234 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 235 | TEST(DOMStorageDatabaseTest, SimpleWriteAndReadBack) { |
| 236 | DOMStorageDatabase db; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 237 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 238 | DOMStorageValuesMap storage; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 239 | CreateMapWithValues(&storage); |
| 240 | |
| 241 | EXPECT_TRUE(db.CommitChanges(false, storage)); |
| 242 | CheckValuesMatch(&db, storage); |
| 243 | } |
| 244 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 245 | TEST(DOMStorageDatabaseTest, WriteWithClear) { |
| 246 | DOMStorageDatabase db; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 247 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 248 | DOMStorageValuesMap storage; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 249 | 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) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 257 | base::NullableString16(ASCIIToUTF16("test"), false); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 258 | 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 Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 267 | TEST(DOMStorageDatabaseTest, UpgradeFromV1ToV2WithData) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 268 | const base::string16 kCannedKey = ASCIIToUTF16("foo"); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 269 | const base::NullableString16 kCannedValue(ASCIIToUTF16("bar"), false); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 270 | DOMStorageValuesMap expected; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 271 | expected[kCannedKey] = kCannedValue; |
| 272 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 273 | DOMStorageDatabase db; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 274 | 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 Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 281 | EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 282 | |
| 283 | CheckValuesMatch(&db, expected); |
| 284 | } |
| 285 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 286 | TEST(DOMStorageDatabaseTest, TestSimpleRemoveOneValue) { |
| 287 | DOMStorageDatabase db; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 288 | |
| 289 | ASSERT_TRUE(db.LazyOpen(true)); |
| 290 | const base::string16 kCannedKey = ASCIIToUTF16("test"); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 291 | const base::NullableString16 kCannedValue(ASCIIToUTF16("data"), false); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 292 | DOMStorageValuesMap expected; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 293 | 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 Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 299 | DOMStorageValuesMap values; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 300 | // A null string in the map should mean that that key gets |
| 301 | // removed. |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 302 | values[kCannedKey] = base::NullableString16(); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 303 | EXPECT_TRUE(db.CommitChanges(false, values)); |
| 304 | |
| 305 | expected.clear(); |
| 306 | CheckValuesMatch(&db, expected); |
| 307 | } |
| 308 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 309 | TEST(DOMStorageDatabaseTest, TestCanOpenAndReadWebCoreDatabase) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 310 | 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 Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 318 | ASSERT_TRUE(base::PathExists(webcore_database)); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 319 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 320 | DOMStorageDatabase db(webcore_database); |
| 321 | DOMStorageValuesMap values; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 322 | db.ReadAllValues(&values); |
| 323 | EXPECT_TRUE(db.IsOpen()); |
| 324 | EXPECT_EQ(2u, values.size()); |
| 325 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 326 | DOMStorageValuesMap::const_iterator it = |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 327 | 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 Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 339 | TEST(DOMStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 340 | // Write into the temporary file first. |
| 341 | base::ScopedTempDir temp_dir; |
| 342 | ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 343 | base::FilePath file_name = |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 344 | temp_dir.path().AppendASCII("TestDOMStorageDatabase.db"); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 345 | |
| 346 | const char kData[] = "I am not a database."; |
| 347 | file_util::WriteFile(file_name, kData, strlen(kData)); |
| 348 | |
| 349 | { |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 350 | sql::ScopedErrorIgnorer ignore_errors; |
| 351 | ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ); |
| 352 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 353 | // 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 Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 356 | DOMStorageDatabase db(file_name); |
| 357 | DOMStorageValuesMap values; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 358 | 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 Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 364 | |
| 365 | ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 366 | } |
| 367 | |
| 368 | { |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 369 | sql::ScopedErrorIgnorer ignore_errors; |
| 370 | ignore_errors.IgnoreError(SQLITE_CANTOPEN); |
| 371 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 372 | // Try to open a directory, we should fail gracefully and not attempt |
| 373 | // to delete it. |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 374 | DOMStorageDatabase db(temp_dir.path()); |
| 375 | DOMStorageValuesMap values; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 376 | 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 Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 387 | EXPECT_TRUE(base::PathExists(temp_dir.path())); |
| 388 | |
| 389 | ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 390 | } |
| 391 | } |
| 392 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 393 | } // namespace content |