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

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

Issue 9159020: Create a class to represent a DOM Storage Database. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Addressed a couple of things I noticed :) Created 8 years, 10 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
« no previous file with comments | « webkit/dom_storage/dom_storage_database.cc ('k') | webkit/dom_storage/webkit_dom_storage.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_path.h"
8 #include "base/file_util.h"
9 #include "base/path_service.h"
10 #include "base/scoped_temp_dir.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 DomStorageDatabase::DomStorageDatabase()
18 : db_(NULL),
19 failed_to_open_(false),
20 tried_to_recreate_(false) {
21 // This constructor allows us to bypass the DCHECK in the other
22 // constructor that verifies a valid file path was passed to
23 // back the database. We want to be able to do this in unit
24 // tests to use databases in memory.
michaeln 2012/02/08 06:11:33 this comment seems useful since the ctor here is s
25 }
26
27 void CreateV1Table(sql::Connection* db) {
28 ASSERT_FALSE(db->is_open());
29 ASSERT_TRUE(db->OpenInMemory());
30 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
31 ASSERT_TRUE(db->Execute(
32 "CREATE TABLE IF NOT EXISTS ItemTable ("
33 "key TEXT UNIQUE ON CONFLICT REPLACE, "
34 "value TEXT NOT NULL ON CONFLICT FAIL)"));
35 }
36
37 void CreateInvalidTable(sql::Connection* db) {
38 // Create a table with the value type as FLOAT - this is "invalid"
39 // as far as the DOM Storage db is concerned.
40 ASSERT_FALSE(db->is_open());
41 ASSERT_TRUE(db->OpenInMemory());
42 ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
43 ASSERT_TRUE(db->Execute(
44 "CREATE TABLE IF NOT EXISTS ItemTable ("
45 "key TEXT UNIQUE ON CONFLICT REPLACE, "
46 "value FLOAT NOT NULL ON CONFLICT FAIL)"));
47 }
48
49 void InsertDataV1(sql::Connection* db,
50 const string16& key,
51 const string16& value) {
52 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE,
53 "INSERT INTO ItemTable VALUES (?,?)"));
54 statement.BindString16(0, key);
55 statement.BindString16(1, value);
56 ASSERT_TRUE(statement.is_valid());
57 statement.Run();
58 }
59
60 void CheckValuesMatch(DomStorageDatabase* db,
61 const DomStorageDatabase::ValuesMap& expected) {
62 DomStorageDatabase::ValuesMap values_read;
63 db->ReadAllValues(&values_read);
64 EXPECT_EQ(expected.size(), values_read.size());
65
66 DomStorageDatabase::ValuesMap::const_iterator it = values_read.begin();
67 for (; it != values_read.end(); ++it) {
68 string16 key = it->first;
69 NullableString16 value = it->second;
70 NullableString16 expected_value = expected.find(key)->second;
71 EXPECT_EQ(expected_value.string(), value.string());
72 EXPECT_EQ(expected_value.is_null(), value.is_null());
73 }
74 }
75
76 void VerifySchema(sql::Connection* db) {
77 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE,
78 "SELECT * from ItemTable LIMIT 1"));
79 EXPECT_TRUE(db->DoesTableExist("ItemTable"));
80 // Ensure that we've got the colums we expect and they are of the
81 // correct type.
82 EXPECT_TRUE(db->DoesColumnExist("ItemTable", "key"));
83 EXPECT_TRUE(db->DoesColumnExist("ItemTable", "value"));
84 EXPECT_EQ(sql::COLUMN_TYPE_TEXT, statement.DeclaredColumnType(0));
85 EXPECT_EQ(sql::COLUMN_TYPE_BLOB, statement.DeclaredColumnType(1));
86 }
87
88 void CreateMapWithValues(DomStorageDatabase::ValuesMap* values) {
89 string16 kCannedKeys[] = {
90 ASCIIToUTF16("test"),
91 ASCIIToUTF16("company"),
92 ASCIIToUTF16("date"),
93 ASCIIToUTF16("empty")
94 };
95 NullableString16 kCannedValues[] = {
96 NullableString16(ASCIIToUTF16("123"), false),
97 NullableString16(ASCIIToUTF16("Google"), false),
98 NullableString16(ASCIIToUTF16("18-01-2012"), false),
99 NullableString16(ASCIIToUTF16(""), false)
100 };
101 for (unsigned i = 0; i < sizeof(kCannedKeys) / sizeof(kCannedKeys[0]); i++)
102 (*values)[kCannedKeys[i]] = kCannedValues[i];
103 }
104
105 TEST(DomStorageDatabaseTest, SimpleOpenAndClose) {
106 DomStorageDatabase db;
107 ASSERT_TRUE(db.LazyOpen(true));
108 VerifySchema(db.db_.get());
109 db.Close();
110 EXPECT_FALSE(db.IsOpen());
111 }
112
113 TEST(DomStorageDatabaseTest, TestLazyOpenIsLazy) {
114 // This test needs to operate with a file on disk to ensure that we will
115 // open a file that already exists when only invoking ReadAllValues.
116 ScopedTempDir temp_dir;
117 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
118 FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");
119
120 DomStorageDatabase db(file_name);
121 EXPECT_FALSE(db.IsOpen());
122 DomStorageDatabase::ValuesMap values;
123 db.ReadAllValues(&values);
124 EXPECT_FALSE(db.IsOpen());
125 values[ASCIIToUTF16("key")] = NullableString16(ASCIIToUTF16("value"), false);
126 db.CommitChanges(false, values);
127 EXPECT_TRUE(db.IsOpen());
128
129 db.Close();
130 ASSERT_FALSE(db.IsOpen());
131
132 db.ReadAllValues(&values);
133 EXPECT_TRUE(db.IsOpen());
134 }
135
136 TEST(DomStorageDatabaseTest, TestLazyOpenUpgradesV1TableToV2) {
137 DomStorageDatabase db;
138 db.db_.reset(new sql::Connection());
139 CreateV1Table(db.db_.get());
140 db.Close();
141
142 EXPECT_TRUE(db.LazyOpen(true));
143 VerifySchema(db.db_.get());
144 }
145
146 TEST(DomStorageDatabaseTest, TestFailedUpgrade) {
147 DomStorageDatabase db;
148 db.db_.reset(new sql::Connection());
149 CreateInvalidTable(db.db_.get());
150
151 EXPECT_FALSE(db.UpgradeVersion1To2IfNeeded());
152
153 db.Close();
154
155 // LazyOpen should be able to deal with the failed upgrade by
156 // dropping the table and creating a new one.
157 EXPECT_TRUE(db.LazyOpen(true));
158 VerifySchema(db.db_.get());
159 }
160
161
162 TEST(DomStorageDatabaseTest, TestIsOpen) {
163 DomStorageDatabase db;
164 EXPECT_FALSE(db.IsOpen());
165 ASSERT_TRUE(db.LazyOpen(true));
166 EXPECT_TRUE(db.IsOpen());
167 db.Close();
168 EXPECT_FALSE(db.IsOpen());
169 }
170
171 TEST(DomStorageDatabaseTest, SimpleWriteAndReadBack) {
172 DomStorageDatabase db;
173
174 DomStorageDatabase::ValuesMap storage;
175 CreateMapWithValues(&storage);
176
177 // Test write.
178 EXPECT_TRUE(db.CommitChanges(false, storage));
179
180 // CheckValuesMatch will invoke DomStorageDatabase::ReadAllValues
181 // to test reading.
182 CheckValuesMatch(&db, storage);
183 }
184
185 TEST(DomStorageDatabaseTest, WriteWithClear) {
186 DomStorageDatabase db;
187
188 DomStorageDatabase::ValuesMap storage;
189 CreateMapWithValues(&storage);
190
191 ASSERT_TRUE(db.CommitChanges(false, storage));
192 CheckValuesMatch(&db, storage);
193
194 // Insert some values, clearing the database first.
195 storage.clear();
196 storage[ASCIIToUTF16("another_key")] =
197 NullableString16(ASCIIToUTF16("test"), false);
198 ASSERT_TRUE(db.CommitChanges(true, storage));
199 CheckValuesMatch(&db, storage);
200
201 // Now clear the values without inserting any new ones.
202 storage.clear();
203 ASSERT_TRUE(db.CommitChanges(true, storage));
204 CheckValuesMatch(&db, storage);
205 }
206
207 TEST(DomStorageDatabaseTest, UpgradeFromV1ToV2WithData) {
208 const string16 kCannedKey = ASCIIToUTF16("foo");
209 const NullableString16 kCannedValue(ASCIIToUTF16("bar"), false);
210 DomStorageDatabase::ValuesMap expected;
211 expected[kCannedKey] = kCannedValue;
212
213 DomStorageDatabase db;
214 db.db_.reset(new sql::Connection());
215 CreateV1Table(db.db_.get());
216 InsertDataV1(db.db_.get(), kCannedKey, kCannedValue.string());
217
218 ASSERT_TRUE(db.UpgradeVersion1To2IfNeeded());
219
220 VerifySchema(db.db_.get());
221
222 CheckValuesMatch(&db, expected);
223 }
224
225 TEST(DomStorageDatabaseTest, TestOpenCloseDataPreserved) {
226 // This test needs to operate on a file on disk.
227 ScopedTempDir temp_dir;
228 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
229 FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");
230
231 DomStorageDatabase db(file_name);
232
233 ASSERT_TRUE(db.LazyOpen(true));
234
235 const string16 kCannedKey = ASCIIToUTF16("test");
236 const NullableString16 kCannedValue(ASCIIToUTF16("data"), false);
237 DomStorageDatabase::ValuesMap expected;
238 expected[kCannedKey] = kCannedValue;
239 db.CommitChanges(false, expected);
240 db.Close();
241
242 ASSERT_TRUE(db.LazyOpen(true));
243
244 CheckValuesMatch(&db, expected);
245 }
246
247 TEST(DomStorageDatabaseTest, TestSimpleRemoveOneValue) {
248 DomStorageDatabase db;
249
250 ASSERT_TRUE(db.LazyOpen(true));
251 const string16 kCannedKey = ASCIIToUTF16("test");
252 const NullableString16 kCannedValue(ASCIIToUTF16("data"), false);
253 DomStorageDatabase::ValuesMap expected;
254 expected[kCannedKey] = kCannedValue;
255 db.CommitChanges(false, expected);
256
257 CheckValuesMatch(&db, expected);
258
259 DomStorageDatabase::ValuesMap values;
260 // A null string in the map should mean that that key gets
261 // removed.
262 values[kCannedKey] = NullableString16(true);
263 db.CommitChanges(false, values);
264
265 expected.clear();
266 CheckValuesMatch(&db, expected);
267 }
268
269 // TODO(benm): Enable this test in follow up patch once the test data has
270 // landed. (try-bots don't like adding binary files like test databases :) )
271 TEST(DomStorageDatabaseTest, DISABLED_TestCanOpenAndReadWebCoreDatabase) {
272 FilePath webcore_database;
273 PathService::Get(base::DIR_SOURCE_ROOT, &webcore_database);
274 webcore_database = webcore_database.AppendASCII("webkit");
275 webcore_database = webcore_database.AppendASCII("data");
276 webcore_database = webcore_database.AppendASCII("dom_storage");
277 webcore_database =
278 webcore_database.AppendASCII("webcore_test_database.localstorage");
279
280 ASSERT_TRUE(file_util::PathExists(webcore_database));
281
282 DomStorageDatabase db(webcore_database);
283 DomStorageDatabase::ValuesMap values;
284 db.ReadAllValues(&values);
285 EXPECT_TRUE(db.IsOpen());
286 EXPECT_EQ(2u, values.size());
287
288 DomStorageDatabase::ValuesMap::const_iterator it =
289 values.find(ASCIIToUTF16("value"));
290 EXPECT_TRUE(it != values.end());
291 EXPECT_EQ(ASCIIToUTF16("I am in local storage!"), it->second.string());
292
293 it = values.find(ASCIIToUTF16("timestamp"));
294 EXPECT_TRUE(it != values.end());
295 EXPECT_EQ(ASCIIToUTF16("1326738338841"), it->second.string());
296
297 it = values.find(ASCIIToUTF16("not_there"));
298 EXPECT_TRUE(it == values.end());
299 }
300
301 TEST(DomStorageDatabaseTest, TestCanOpenFileThatIsNotADatabase) {
302 // Write into the temporary file first.
303 ScopedTempDir temp_dir;
304 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
305 FilePath file_name = temp_dir.path().AppendASCII("TestDomStorageDatabase.db");
306
307 const char kData[] = "I am not a database.";
308 file_util::WriteFile(file_name, kData, strlen(kData));
309
310 {
311 // Try and open the file. We should end up deleting it and creating a new
312 // file, so everything should actually succeed.
313 DomStorageDatabase db(file_name);
314 DomStorageDatabase::ValuesMap values;
315 CreateMapWithValues(&values);
316 EXPECT_TRUE(db.CommitChanges(true, values));
317 EXPECT_TRUE(db.CommitChanges(false, values));
318 EXPECT_TRUE(db.IsOpen());
319
320 CheckValuesMatch(&db, values);
321 }
322
323 {
324 // Try to open a directory, we should fail gracefully.
325 DomStorageDatabase db(temp_dir.path());
326 DomStorageDatabase::ValuesMap values;
327 CreateMapWithValues(&values);
328 EXPECT_FALSE(db.CommitChanges(true, values));
329 EXPECT_FALSE(db.CommitChanges(false, values));
330 EXPECT_FALSE(db.IsOpen());
331
332 values.clear();
333
334 db.ReadAllValues(&values);
335 EXPECT_EQ(0u, values.size());
336 EXPECT_FALSE(db.IsOpen());
337 }
338 }
339
340 } // namespace dom_storage
OLDNEW
« no previous file with comments | « webkit/dom_storage/dom_storage_database.cc ('k') | webkit/dom_storage/webkit_dom_storage.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698