Index: webkit/dom_storage/local_storage_database_unittest.cc |
diff --git a/webkit/dom_storage/local_storage_database_unittest.cc b/webkit/dom_storage/local_storage_database_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c1ad1c764d205aeb5b4b0a8d921ae5b4ae180961 |
--- /dev/null |
+++ b/webkit/dom_storage/local_storage_database_unittest.cc |
@@ -0,0 +1,230 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "webkit/dom_storage/local_storage_database.h" |
+ |
+#include "base/file_path.h" |
+#include "base/scoped_temp_dir.h" |
+#include "base/utf_string_conversions.h" |
+#include "sql/statement.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace dom_storage { |
+ |
+class LocalStorageDatabaseTest : public testing::Test { |
+ protected: |
+ virtual void SetUp() { |
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
+ file_name_ = temp_dir_.path().AppendASCII("TestLocalStorageDatabase.db"); |
+ } |
+ |
+ void CreateV1Table(sql::Connection* db) { |
+ ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable")); |
+ ASSERT_TRUE(db->Execute( |
+ "CREATE TABLE IF NOT EXISTS ItemTable (" |
+ "key TEXT UNIQUE ON CONFLICT REPLACE, " |
+ "value TEXT NOT NULL ON CONFLICT FAIL)")); |
+ } |
+ |
+ void InsertDataV1(sql::Connection* db, |
+ const string16& key, |
+ const string16& value) { |
+ sql::Statement stmt(db->GetCachedStatement(SQL_FROM_HERE, |
+ "INSERT INTO ItemTable VALUES (?,?)")); |
+ stmt.BindString16(0, key); |
+ stmt.BindString16(1, value); |
+ ASSERT_TRUE(stmt.is_valid()); |
+ stmt.Run(); |
+ } |
+ |
+ void InsertDataV2(sql::Connection* db, |
+ const string16& key, |
+ const string16& value) { |
+ sql::Statement stmt(db->GetCachedStatement(SQL_FROM_HERE, |
+ "INSERT INTO ItemTable VALUES (?,?)")); |
+ stmt.BindString16(0, key); |
+ stmt.BindBlob(1, UTF16ToUTF8(value).c_str(), value.size()); |
+ ASSERT_TRUE(stmt.is_valid()); |
+ stmt.Run(); |
+ } |
+ |
+ std::map<string16, string16> ReadAllRows(sql::Connection* db) { |
+ std::map<string16, string16> values; |
+ sql::Statement stmt(db->GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT * from ItemTable")); |
+ EXPECT_TRUE(stmt.is_valid()); |
+ while (stmt.Step()) { |
+ string16 key = stmt.ColumnString16(0); |
+ |
+ std::string result; |
+ stmt.ColumnBlobAsString(1, &result); |
+ string16 value = UTF8ToUTF16(result); |
+ values[key] = value; |
+ } |
+ return values; |
+ } |
+ |
+ void CheckValuesMatch(sql::Connection* db, |
+ const std::map<string16, string16>& expected) { |
+ const std::map<string16, string16> values_read = ReadAllRows(db); |
+ EXPECT_EQ(expected.size(), values_read.size()); |
+ |
+ std::map<string16, string16>::const_iterator it = values_read.begin(); |
+ for (; it != values_read.end(); ++it) { |
+ string16 key = it->first; |
+ string16 value = it->second; |
+ EXPECT_EQ(expected.find(key)->second, value); |
+ } |
+ } |
+ |
+ ScopedTempDir temp_dir_; |
+ FilePath file_name_; |
+}; |
+ |
+TEST_F(LocalStorageDatabaseTest, SimpleOpenInitAndClose) { |
+ LocalStorageDatabase db(file_name_); |
+ ASSERT_TRUE(db.Open()); |
+ ASSERT_TRUE(db.Init()); |
+ EXPECT_EQ(2, db.GetVersionNumber()); |
+ EXPECT_TRUE(db.db_->DoesTableExist("ItemTable")); |
+ // Ensure that we've got the colums we expect. |
+ EXPECT_TRUE(db.db_->DoesColumnExist("ItemTable", "key")); |
+ EXPECT_TRUE(db.db_->DoesColumnExist("ItemTable", "value")); |
+ { |
+ sql::Statement stmt(db.db_->GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT * from ItemTable LIMIT 1")); |
+ EXPECT_EQ(sql::COLUMN_TYPE_TEXT, stmt.DeclaredColumnType(0)); |
+ EXPECT_EQ(sql::COLUMN_TYPE_BLOB, stmt.DeclaredColumnType(1)); |
+ } |
+ db.Close(); |
+ EXPECT_FALSE(db.IsOpen()); |
+} |
+ |
+TEST_F(LocalStorageDatabaseTest, TestInitUpgradesV1TableToV2) { |
+ LocalStorageDatabase db(file_name_); |
+ ASSERT_TRUE(db.Open()); |
+ CreateV1Table(db.db_.get()); |
+ db.Close(); |
+ |
+ ASSERT_TRUE(db.Open()); |
+ EXPECT_EQ(1, db.GetVersionNumber()); |
+ ASSERT_TRUE(db.Init()); |
+ EXPECT_EQ(2, db.GetVersionNumber()); |
+ sql::Statement stmt(db.db_->GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT * from ItemTable LIMIT 1")); |
+ EXPECT_EQ(sql::COLUMN_TYPE_TEXT, stmt.DeclaredColumnType(0)); |
+ EXPECT_EQ(sql::COLUMN_TYPE_BLOB, stmt.DeclaredColumnType(1)); |
+} |
+ |
+TEST_F(LocalStorageDatabaseTest, TestIsOpen) { |
+ LocalStorageDatabase db(file_name_); |
+ EXPECT_FALSE(db.IsOpen()); |
+ ASSERT_TRUE(db.Open()); |
+ EXPECT_TRUE(db.IsOpen()); |
+ db.Close(); |
+ EXPECT_FALSE(db.IsOpen()); |
+} |
+ |
+TEST_F(LocalStorageDatabaseTest, SimpleRead) { |
+ LocalStorageDatabase db(file_name_); |
+ ASSERT_TRUE(db.Open()); |
+ ASSERT_TRUE(db.Init()); |
+ |
+ const string16 kCannedKey = ASCIIToUTF16("name"); |
+ const string16 kCannedValue = ASCIIToUTF16("Joe Bloggs"); |
+ |
+ InsertDataV2(db.db_.get(), kCannedKey, kCannedValue); |
+ std::map<string16, string16> values = db.ReadAllValues(); |
+ |
+ EXPECT_EQ(1u, values.size()); |
+ EXPECT_NE(values.end(), values.find(kCannedKey)); |
+ EXPECT_EQ(kCannedValue, values[kCannedKey]); |
+} |
+ |
+TEST_F(LocalStorageDatabaseTest, SimpleWrite) { |
+ LocalStorageDatabase db(file_name_); |
+ ASSERT_TRUE(db.Open()); |
+ ASSERT_TRUE(db.Init()); |
+ |
+ std::map<string16, string16> storage; |
+ string16 kCannedKeys[] = { |
+ ASCIIToUTF16("test"), |
+ ASCIIToUTF16("company"), |
+ ASCIIToUTF16("date") |
+ }; |
+ string16 kCannedValues[] = { |
+ ASCIIToUTF16("123"), |
+ ASCIIToUTF16("Google"), |
+ ASCIIToUTF16("18-01-2012") |
+ }; |
+ for (int i = 0; i < 3; i++) { |
+ storage[kCannedKeys[i]] = kCannedValues[i]; |
+ } |
+ |
+ ASSERT_TRUE(db.WriteAllValues(storage)); |
+ |
+ CheckValuesMatch(db.db_.get(), storage); |
+} |
+ |
+TEST_F(LocalStorageDatabaseTest, UpgradeFromV1ToV2NoData) { |
+ LocalStorageDatabase db(file_name_); |
+ ASSERT_TRUE(db.Open()); |
+ CreateV1Table(db.db_.get()); |
+ |
+ // The database has V1 structure, try to update it to V2. |
+ sql::Statement stmt(db.db_->GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT value from ItemTable LIMIT 1")); |
+ ASSERT_EQ(sql::COLUMN_TYPE_TEXT, stmt.DeclaredColumnType(0)); |
+ |
+ ASSERT_TRUE(db.UpgradeVersion1To2IfNeeded()); |
+ |
+ // Verify the db now has V2 structure. |
+ sql::Statement stmt2(db.db_->GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT value from ItemTable LIMIT 1")); |
+ EXPECT_EQ(sql::COLUMN_TYPE_BLOB, stmt2.DeclaredColumnType(0)); |
+} |
+ |
+TEST_F(LocalStorageDatabaseTest, UpgradeFromV1ToV2WithData) { |
+ LocalStorageDatabase db(file_name_); |
+ ASSERT_TRUE(db.Open()); |
+ CreateV1Table(db.db_.get()); |
+ |
+ // The database has V1 structure, try to update it to V2. |
+ sql::Statement stmt(db.db_->GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT value from ItemTable LIMIT 1")); |
+ ASSERT_EQ(sql::COLUMN_TYPE_TEXT, stmt.DeclaredColumnType(0)); |
+ |
+ const string16 kCannedKey = ASCIIToUTF16("foo"); |
+ const string16 kCannedValue = ASCIIToUTF16("bar"); |
+ InsertDataV1(db.db_.get(), kCannedKey, kCannedValue); |
+ |
+ ASSERT_TRUE(db.UpgradeVersion1To2IfNeeded()); |
+ |
+ // Verify the db now has V2 structure. |
+ sql::Statement stmt2(db.db_->GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT value from ItemTable LIMIT 1")); |
+ EXPECT_EQ(sql::COLUMN_TYPE_BLOB, stmt2.DeclaredColumnType(0)); |
+ |
+ std::map<string16, string16> expected; |
+ expected[kCannedKey] = kCannedValue; |
+ CheckValuesMatch(db.db_.get(), expected); |
+} |
+ |
+TEST_F(LocalStorageDatabaseTest, TestOpenCloseDataPreserved) { |
+ LocalStorageDatabase db(file_name_); |
+ ASSERT_TRUE(db.Open()); |
+ ASSERT_TRUE(db.Init()); |
+ |
+ const string16 kCannedKey = ASCIIToUTF16("test"); |
+ const string16 kCannedValue = ASCIIToUTF16("data"); |
+ InsertDataV2(db.db_.get(), kCannedKey, kCannedValue); |
+ db.Close(); |
+ |
+ db.Open(); |
+ std::map<string16, string16> expected; |
+ expected[kCannedKey] = kCannedValue; |
+ CheckValuesMatch(db.db_.get(), expected); |
+} |
+ |
+} // namespace dom_storage |