Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(388)

Side by Side Diff: webkit/dom_storage/dom_storage_database_unittest.cc

Issue 15990007: Move dom_storage to new locations. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "webkit/dom_storage/dom_storage_database.h"
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/utf_string_conversions.h"
12 #include "sql/statement.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace dom_storage {
16
17 void CreateV1Table(sql::Connection* db) {
18 ASSERT_TRUE(db->is_open());
19 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
20 ASSERT_TRUE(db->Execute(
21 "CREATE TABLE ItemTable ("
22 "key TEXT UNIQUE ON CONFLICT REPLACE, "
23 "value TEXT NOT NULL ON CONFLICT FAIL)"));
24 }
25
26 void CreateV2Table(sql::Connection* db) {
27 ASSERT_TRUE(db->is_open());
28 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
29 ASSERT_TRUE(db->Execute(
30 "CREATE TABLE ItemTable ("
31 "key TEXT UNIQUE ON CONFLICT REPLACE, "
32 "value BLOB NOT NULL ON CONFLICT FAIL)"));
33 }
34
35 void CreateInvalidKeyColumnTable(sql::Connection* db) {
36 // Create a table with the key type as FLOAT - this is "invalid"
37 // as far as the DOM Storage db is concerned.
38 ASSERT_TRUE(db->is_open());
39 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
40 ASSERT_TRUE(db->Execute(
41 "CREATE TABLE IF NOT EXISTS ItemTable ("
42 "key FLOAT UNIQUE ON CONFLICT REPLACE, "
43 "value BLOB NOT NULL ON CONFLICT FAIL)"));
44 }
45 void CreateInvalidValueColumnTable(sql::Connection* db) {
46 // Create a table with the value type as FLOAT - this is "invalid"
47 // as far as the DOM Storage db is concerned.
48 ASSERT_TRUE(db->is_open());
49 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
50 ASSERT_TRUE(db->Execute(
51 "CREATE TABLE IF NOT EXISTS ItemTable ("
52 "key TEXT UNIQUE ON CONFLICT REPLACE, "
53 "value FLOAT NOT NULL ON CONFLICT FAIL)"));
54 }
55
56 void InsertDataV1(sql::Connection* db,
57 const base::string16& key,
58 const base::string16& value) {
59 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE,
60 "INSERT INTO ItemTable VALUES (?,?)"));
61 statement.BindString16(0, key);
62 statement.BindString16(1, value);
63 ASSERT_TRUE(statement.is_valid());
64 statement.Run();
65 }
66
67 void CheckValuesMatch(DomStorageDatabase* db,
68 const ValuesMap& expected) {
69 ValuesMap values_read;
70 db->ReadAllValues(&values_read);
71 EXPECT_EQ(expected.size(), values_read.size());
72
73 ValuesMap::const_iterator it = values_read.begin();
74 for (; it != values_read.end(); ++it) {
75 base::string16 key = it->first;
76 NullableString16 value = it->second;
77 NullableString16 expected_value = expected.find(key)->second;
78 EXPECT_EQ(expected_value.string(), value.string());
79 EXPECT_EQ(expected_value.is_null(), value.is_null());
80 }
81 }
82
83 void CreateMapWithValues(ValuesMap* values) {
84 base::string16 kCannedKeys[] = {
85 ASCIIToUTF16("test"),
86 ASCIIToUTF16("company"),
87 ASCIIToUTF16("date"),
88 ASCIIToUTF16("empty")
89 };
90 NullableString16 kCannedValues[] = {
91 NullableString16(ASCIIToUTF16("123"), false),
92 NullableString16(ASCIIToUTF16("Google"), false),
93 NullableString16(ASCIIToUTF16("18-01-2012"), false),
94 NullableString16(base::string16(), false)
95 };
96 for (unsigned i = 0; i < sizeof(kCannedKeys) / sizeof(kCannedKeys[0]); i++)
97 (*values)[kCannedKeys[i]] = kCannedValues[i];
98 }
99
100 TEST(DomStorageDatabaseTest, SimpleOpenAndClose) {
101 DomStorageDatabase db;
102 EXPECT_FALSE(db.IsOpen());
103 ASSERT_TRUE(db.LazyOpen(true));
104 EXPECT_TRUE(db.IsOpen());
105 EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
106 db.Close();
107 EXPECT_FALSE(db.IsOpen());
108 }
109
110 TEST(DomStorageDatabaseTest, CloseEmptyDatabaseDeletesFile) {
111 base::ScopedTempDir temp_dir;
112 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
113 base::FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase .db");
114 ValuesMap storage;
115 CreateMapWithValues(&storage);
116
117 // First test the case that explicitly clearing the database will
118 // trigger its deletion from disk.
119 {
120 DomStorageDatabase db(file_name);
121 EXPECT_EQ(file_name, db.file_path());
122 ASSERT_TRUE(db.CommitChanges(false, storage));
123 }
124 EXPECT_TRUE(file_util::PathExists(file_name));
125
126 {
127 // Check that reading an existing db with data in it
128 // keeps the DB on disk on close.
129 DomStorageDatabase db(file_name);
130 ValuesMap values;
131 db.ReadAllValues(&values);
132 EXPECT_EQ(storage.size(), values.size());
133 }
134
135 EXPECT_TRUE(file_util::PathExists(file_name));
136 storage.clear();
137
138 {
139 DomStorageDatabase db(file_name);
140 ASSERT_TRUE(db.CommitChanges(true, storage));
141 }
142 EXPECT_FALSE(file_util::PathExists(file_name));
143
144 // Now ensure that a series of updates and removals whose net effect
145 // is an empty database also triggers deletion.
146 CreateMapWithValues(&storage);
147 {
148 DomStorageDatabase db(file_name);
149 ASSERT_TRUE(db.CommitChanges(false, storage));
150 }
151
152 EXPECT_TRUE(file_util::PathExists(file_name));
153
154 {
155 DomStorageDatabase db(file_name);
156 ASSERT_TRUE(db.CommitChanges(false, storage));
157 ValuesMap::iterator it = storage.begin();
158 for (; it != storage.end(); ++it)
159 it->second = NullableString16(true);
160 ASSERT_TRUE(db.CommitChanges(false, storage));
161 }
162 EXPECT_FALSE(file_util::PathExists(file_name));
163 }
164
165 TEST(DomStorageDatabaseTest, TestLazyOpenIsLazy) {
166 // This test needs to operate with a file on disk to ensure that we will
167 // open a file that already exists when only invoking ReadAllValues.
168 base::ScopedTempDir temp_dir;
169 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
170 base::FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase .db");
171
172 DomStorageDatabase db(file_name);
173 EXPECT_FALSE(db.IsOpen());
174 ValuesMap values;
175 db.ReadAllValues(&values);
176 // Reading an empty db should not open the database.
177 EXPECT_FALSE(db.IsOpen());
178
179 values[ASCIIToUTF16("key")] = NullableString16(ASCIIToUTF16("value"), false);
180 db.CommitChanges(false, values);
181 // Writing content should open the database.
182 EXPECT_TRUE(db.IsOpen());
183
184 db.Close();
185 ASSERT_FALSE(db.IsOpen());
186
187 // Reading from an existing database should open the database.
188 CheckValuesMatch(&db, values);
189 EXPECT_TRUE(db.IsOpen());
190 }
191
192 TEST(DomStorageDatabaseTest, TestDetectSchemaVersion) {
193 DomStorageDatabase db;
194 db.db_.reset(new sql::Connection());
195 ASSERT_TRUE(db.db_->OpenInMemory());
196
197 CreateInvalidValueColumnTable(db.db_.get());
198 EXPECT_EQ(DomStorageDatabase::INVALID, db.DetectSchemaVersion());
199
200 CreateInvalidKeyColumnTable(db.db_.get());
201 EXPECT_EQ(DomStorageDatabase::INVALID, db.DetectSchemaVersion());
202
203 CreateV1Table(db.db_.get());
204 EXPECT_EQ(DomStorageDatabase::V1, db.DetectSchemaVersion());
205
206 CreateV2Table(db.db_.get());
207 EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
208 }
209
210 TEST(DomStorageDatabaseTest, TestLazyOpenUpgradesDatabase) {
211 // This test needs to operate with a file on disk so that we
212 // can create a table at version 1 and then close it again
213 // so that LazyOpen sees there is work to do (LazyOpen will return
214 // early if the database is already open).
215 base::ScopedTempDir temp_dir;
216 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
217 base::FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase .db");
218
219 DomStorageDatabase db(file_name);
220 db.db_.reset(new sql::Connection());
221 ASSERT_TRUE(db.db_->Open(file_name));
222 CreateV1Table(db.db_.get());
223 db.Close();
224
225 EXPECT_TRUE(db.LazyOpen(true));
226 EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
227 }
228
229 TEST(DomStorageDatabaseTest, SimpleWriteAndReadBack) {
230 DomStorageDatabase db;
231
232 ValuesMap storage;
233 CreateMapWithValues(&storage);
234
235 EXPECT_TRUE(db.CommitChanges(false, storage));
236 CheckValuesMatch(&db, storage);
237 }
238
239 TEST(DomStorageDatabaseTest, WriteWithClear) {
240 DomStorageDatabase db;
241
242 ValuesMap storage;
243 CreateMapWithValues(&storage);
244
245 ASSERT_TRUE(db.CommitChanges(false, storage));
246 CheckValuesMatch(&db, storage);
247
248 // Insert some values, clearing the database first.
249 storage.clear();
250 storage[ASCIIToUTF16("another_key")] =
251 NullableString16(ASCIIToUTF16("test"), false);
252 ASSERT_TRUE(db.CommitChanges(true, storage));
253 CheckValuesMatch(&db, storage);
254
255 // Now clear the values without inserting any new ones.
256 storage.clear();
257 ASSERT_TRUE(db.CommitChanges(true, storage));
258 CheckValuesMatch(&db, storage);
259 }
260
261 TEST(DomStorageDatabaseTest, UpgradeFromV1ToV2WithData) {
262 const base::string16 kCannedKey = ASCIIToUTF16("foo");
263 const NullableString16 kCannedValue(ASCIIToUTF16("bar"), false);
264 ValuesMap expected;
265 expected[kCannedKey] = kCannedValue;
266
267 DomStorageDatabase db;
268 db.db_.reset(new sql::Connection());
269 ASSERT_TRUE(db.db_->OpenInMemory());
270 CreateV1Table(db.db_.get());
271 InsertDataV1(db.db_.get(), kCannedKey, kCannedValue.string());
272
273 ASSERT_TRUE(db.UpgradeVersion1To2());
274
275 EXPECT_EQ(DomStorageDatabase::V2, db.DetectSchemaVersion());
276
277 CheckValuesMatch(&db, expected);
278 }
279
280 TEST(DomStorageDatabaseTest, TestSimpleRemoveOneValue) {
281 DomStorageDatabase db;
282
283 ASSERT_TRUE(db.LazyOpen(true));
284 const base::string16 kCannedKey = ASCIIToUTF16("test");
285 const NullableString16 kCannedValue(ASCIIToUTF16("data"), false);
286 ValuesMap expected;
287 expected[kCannedKey] = kCannedValue;
288
289 // First write some data into the database.
290 ASSERT_TRUE(db.CommitChanges(false, expected));
291 CheckValuesMatch(&db, expected);
292
293 ValuesMap values;
294 // A null string in the map should mean that that key gets
295 // removed.
296 values[kCannedKey] = NullableString16(true);
297 EXPECT_TRUE(db.CommitChanges(false, values));
298
299 expected.clear();
300 CheckValuesMatch(&db, expected);
301 }
302
303 TEST(DomStorageDatabaseTest, TestCanOpenAndReadWebCoreDatabase) {
304 base::FilePath webcore_database;
305 PathService::Get(base::DIR_SOURCE_ROOT, &webcore_database);
306 webcore_database = webcore_database.AppendASCII("webkit");
307 webcore_database = webcore_database.AppendASCII("data");
308 webcore_database = webcore_database.AppendASCII("dom_storage");
309 webcore_database =
310 webcore_database.AppendASCII("webcore_test_database.localstorage");
311
312 ASSERT_TRUE(file_util::PathExists(webcore_database));
313
314 DomStorageDatabase db(webcore_database);
315 ValuesMap values;
316 db.ReadAllValues(&values);
317 EXPECT_TRUE(db.IsOpen());
318 EXPECT_EQ(2u, values.size());
319
320 ValuesMap::const_iterator it =
321 values.find(ASCIIToUTF16("value"));
322 EXPECT_TRUE(it != values.end());
323 EXPECT_EQ(ASCIIToUTF16("I am in local storage!"), it->second.string());
324
325 it = values.find(ASCIIToUTF16("timestamp"));
326 EXPECT_TRUE(it != values.end());
327 EXPECT_EQ(ASCIIToUTF16("1326738338841"), it->second.string());
328
329 it = values.find(ASCIIToUTF16("not_there"));
330 EXPECT_TRUE(it == values.end());
331 }
332
333 TEST(DomStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) {
334 // Write into the temporary file first.
335 base::ScopedTempDir temp_dir;
336 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
337 base::FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase .db");
338
339 const char kData[] = "I am not a database.";
340 file_util::WriteFile(file_name, kData, strlen(kData));
341
342 {
343 // Try and open the file. As it's not a database, we should end up deleting
344 // it and creating a new, valid file, so everything should actually
345 // succeed.
346 DomStorageDatabase db(file_name);
347 ValuesMap values;
348 CreateMapWithValues(&values);
349 EXPECT_TRUE(db.CommitChanges(true, values));
350 EXPECT_TRUE(db.CommitChanges(false, values));
351 EXPECT_TRUE(db.IsOpen());
352
353 CheckValuesMatch(&db, values);
354 }
355
356 {
357 // Try to open a directory, we should fail gracefully and not attempt
358 // to delete it.
359 DomStorageDatabase db(temp_dir.path());
360 ValuesMap values;
361 CreateMapWithValues(&values);
362 EXPECT_FALSE(db.CommitChanges(true, values));
363 EXPECT_FALSE(db.CommitChanges(false, values));
364 EXPECT_FALSE(db.IsOpen());
365
366 values.clear();
367
368 db.ReadAllValues(&values);
369 EXPECT_EQ(0u, values.size());
370 EXPECT_FALSE(db.IsOpen());
371
372 EXPECT_TRUE(file_util::PathExists(temp_dir.path()));
373 }
374 }
375
376 } // namespace dom_storage
OLDNEW
« no previous file with comments | « webkit/dom_storage/dom_storage_database_adapter.h ('k') | webkit/dom_storage/dom_storage_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698