// Copyright (c) 2011 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 <string> #include "app/sql/statement.h" #include "base/file_util.h" #include "base/memory/scoped_temp_dir.h" #include "base/stl_util-inl.h" #include "base/string16.h" #include "base/string_number_conversions.h" #include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/autofill/autofill_profile.h" #include "chrome/browser/autofill/autofill_type.h" #include "chrome/browser/autofill/credit_card.h" #include "chrome/browser/webdata/autofill_change.h" #include "chrome/browser/webdata/autofill_entry.h" #include "chrome/browser/webdata/web_database.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/guid.h" #include "chrome/test/ui_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" using base::Time; namespace { void AutofillProfile31FromStatement(const sql::Statement& s, AutofillProfile* profile, string16* label, int* unique_id, int64* date_modified) { DCHECK(profile); DCHECK(label); DCHECK(unique_id); DCHECK(date_modified); *label = s.ColumnString16(0); *unique_id = s.ColumnInt(1); profile->SetInfo(NAME_FIRST, s.ColumnString16(2)); profile->SetInfo(NAME_MIDDLE, s.ColumnString16(3)); profile->SetInfo(NAME_LAST,s.ColumnString16(4)); profile->SetInfo(EMAIL_ADDRESS, s.ColumnString16(5)); profile->SetInfo(COMPANY_NAME, s.ColumnString16(6)); profile->SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(7)); profile->SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(8)); profile->SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(9)); profile->SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(10)); profile->SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(11)); profile->SetInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(12)); profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(13)); profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, s.ColumnString16(14)); *date_modified = s.ColumnInt64(15); profile->set_guid(s.ColumnString(16)); EXPECT_TRUE(guid::IsValidGUID(profile->guid())); } void AutofillProfile32FromStatement(const sql::Statement& s, AutofillProfile* profile, string16* label, int64* date_modified) { DCHECK(profile); DCHECK(label); DCHECK(date_modified); profile->set_guid(s.ColumnString(0)); EXPECT_TRUE(guid::IsValidGUID(profile->guid())); *label = s.ColumnString16(1); profile->SetInfo(NAME_FIRST, s.ColumnString16(2)); profile->SetInfo(NAME_MIDDLE, s.ColumnString16(3)); profile->SetInfo(NAME_LAST,s.ColumnString16(4)); profile->SetInfo(EMAIL_ADDRESS, s.ColumnString16(5)); profile->SetInfo(COMPANY_NAME, s.ColumnString16(6)); profile->SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(7)); profile->SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(8)); profile->SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(9)); profile->SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(10)); profile->SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(11)); profile->SetInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(12)); profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(13)); profile->SetInfo(PHONE_FAX_WHOLE_NUMBER, s.ColumnString16(14)); *date_modified = s.ColumnInt64(15); } void AutofillProfile33FromStatement(const sql::Statement& s, AutofillProfile* profile, int64* date_modified) { DCHECK(profile); DCHECK(date_modified); profile->set_guid(s.ColumnString(0)); EXPECT_TRUE(guid::IsValidGUID(profile->guid())); profile->SetInfo(COMPANY_NAME, s.ColumnString16(1)); profile->SetInfo(ADDRESS_HOME_LINE1, s.ColumnString16(2)); profile->SetInfo(ADDRESS_HOME_LINE2, s.ColumnString16(3)); profile->SetInfo(ADDRESS_HOME_CITY, s.ColumnString16(4)); profile->SetInfo(ADDRESS_HOME_STATE, s.ColumnString16(5)); profile->SetInfo(ADDRESS_HOME_ZIP, s.ColumnString16(6)); profile->SetInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(7)); *date_modified = s.ColumnInt64(8); } void CreditCard31FromStatement(const sql::Statement& s, CreditCard* credit_card, string16* label, int* unique_id, std::string* encrypted_number, int64* date_modified) { DCHECK(credit_card); DCHECK(label); DCHECK(unique_id); DCHECK(encrypted_number); DCHECK(date_modified); *label = s.ColumnString16(0); *unique_id = s.ColumnInt(1); credit_card->SetInfo(CREDIT_CARD_NAME, s.ColumnString16(2)); credit_card->SetInfo(CREDIT_CARD_TYPE, s.ColumnString16(3)); credit_card->SetInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(5)); credit_card->SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, s.ColumnString16(6)); int encrypted_number_len = s.ColumnByteLength(10); if (encrypted_number_len) { encrypted_number->resize(encrypted_number_len); memcpy(&(*encrypted_number)[0], s.ColumnBlob(10), encrypted_number_len); } *date_modified = s.ColumnInt64(12); credit_card->set_guid(s.ColumnString(13)); EXPECT_TRUE(guid::IsValidGUID(credit_card->guid())); } void CreditCard32FromStatement(const sql::Statement& s, CreditCard* credit_card, std::string* encrypted_number, int64* date_modified) { DCHECK(credit_card); DCHECK(encrypted_number); DCHECK(date_modified); credit_card->set_guid(s.ColumnString(0)); EXPECT_TRUE(guid::IsValidGUID(credit_card->guid())); credit_card->SetInfo(CREDIT_CARD_NAME, s.ColumnString16(1)); credit_card->SetInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(2)); credit_card->SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, s.ColumnString16(3)); int encrypted_number_len = s.ColumnByteLength(4); if (encrypted_number_len) { encrypted_number->resize(encrypted_number_len); memcpy(&(*encrypted_number)[0], s.ColumnBlob(4), encrypted_number_len); } *date_modified = s.ColumnInt64(5); } } // anonymous namespace // The WebDatabaseMigrationTest encapsulates testing of database migrations. // Specifically, these tests are intended to exercise any schema changes in // the WebDatabase and data migrations that occur in // |WebDatabase::MigrateOldVersionsAsNeeded()|. class WebDatabaseMigrationTest : public testing::Test { public: WebDatabaseMigrationTest() {} virtual ~WebDatabaseMigrationTest() {} virtual void SetUp() { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } protected: // Current tested version number. When adding a migration in // |WebDatabase::MigrateOldVersionsAsNeeded()| and changing the version number // |kCurrentVersionNumber| this value should change to reflect the new version // number and a new migration test added below. static const int kCurrentTestedVersionNumber; FilePath GetDatabasePath() { const FilePath::CharType kWebDatabaseFilename[] = FILE_PATH_LITERAL("TestWebDatabase.sqlite3"); return temp_dir_.path().Append(FilePath(kWebDatabaseFilename)); } // The textual contents of |file| are read from // "chrome/test/data/web_database" and returned in the string |contents|. // Returns true if the file exists and is read successfully, false otherwise. bool GetWebDatabaseData(const FilePath& file, std::string* contents) { FilePath path = ui_test_utils::GetTestFilePath( FilePath(FILE_PATH_LITERAL("web_database")), file); return file_util::PathExists(path) && file_util::ReadFileToString(path, contents); } static int VersionFromConnection(sql::Connection* connection) { // Get version. sql::Statement s(connection->GetUniqueStatement( "SELECT value FROM meta WHERE key='version'")); if (!s.Step()) return 0; return s.ColumnInt(0); } // The sql files located in "chrome/test/data/web_database" were generated by // launching the Chromium application prior to schema change, then using the // sqlite3 command-line application to dump the contents of the "Web Data" // database. // Like this: // > .output version_nn.sql // > .dump void LoadDatabase(const FilePath::StringType& file); // Assertion testing for migrating from version 27 and 28. void MigrateVersion28Assertions(); private: ScopedTempDir temp_dir_; DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest); }; const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 37; void WebDatabaseMigrationTest::LoadDatabase(const FilePath::StringType& file) { std::string contents; ASSERT_TRUE(GetWebDatabaseData(FilePath(file), &contents)); sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); ASSERT_TRUE(connection.Execute(contents.data())); } void WebDatabaseMigrationTest::MigrateVersion28Assertions() { // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // Make sure supports_instant was dropped and instant_url was added. EXPECT_FALSE(connection.DoesColumnExist("keywords", "supports_instant")); EXPECT_TRUE(connection.DoesColumnExist("keywords", "instant_url")); // Check that instant_url is empty. std::string stmt = "SELECT instant_url FROM keywords"; sql::Statement s(connection.GetUniqueStatement(stmt.c_str())); ASSERT_TRUE(s.Step()); EXPECT_EQ(std::string(), s.ColumnString(0)); // Verify the data made it over. stmt = "SELECT id, short_name, keyword, favicon_url, url, " "show_in_default_list, safe_for_autoreplace, originating_url, " "date_created, usage_count, input_encodings, suggest_url, " "prepopulate_id, autogenerate_keyword, logo_id, created_by_policy, " "instant_url FROM keywords"; sql::Statement s2(connection.GetUniqueStatement(stmt.c_str())); ASSERT_TRUE(s2.Step()); EXPECT_EQ(2, s2.ColumnInt(0)); EXPECT_EQ("Google", s2.ColumnString(1)); EXPECT_EQ("google.com", s2.ColumnString(2)); EXPECT_EQ("http://www.google.com/favicon.ico", s2.ColumnString(3)); EXPECT_EQ("{google:baseURL}search?{google:RLZ}{google:acceptedSuggestion}"\ "{google:originalQueryForSuggestion}sourceid=chrome&ie={inputEncoding}"\ "&q={searchTerms}", s2.ColumnString(4)); EXPECT_EQ(1, s2.ColumnInt(5)); EXPECT_EQ(1, s2.ColumnInt(6)); EXPECT_EQ(std::string(), s2.ColumnString(7)); EXPECT_EQ(0, s2.ColumnInt(8)); EXPECT_EQ(0, s2.ColumnInt(9)); EXPECT_EQ(std::string("UTF-8"), s2.ColumnString(10)); EXPECT_EQ(std::string("{google:baseSuggestURL}search?client=chrome&hl=" "{language}&q={searchTerms}"), s2.ColumnString(11)); EXPECT_EQ(1, s2.ColumnInt(12)); EXPECT_EQ(1, s2.ColumnInt(13)); EXPECT_EQ(6245, s2.ColumnInt(14)); EXPECT_EQ(0, s2.ColumnInt(15)); EXPECT_EQ(0, s2.ColumnInt(16)); EXPECT_EQ(std::string(), s2.ColumnString(17)); } } // Tests that the all migrations from an empty database succeed. TEST_F(WebDatabaseMigrationTest, MigrateEmptyToCurrent) { // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // Check that expected tables are present. EXPECT_TRUE(connection.DoesTableExist("meta")); EXPECT_TRUE(connection.DoesTableExist("keywords")); EXPECT_TRUE(connection.DoesTableExist("logins")); EXPECT_TRUE(connection.DoesTableExist("web_app_icons")); EXPECT_TRUE(connection.DoesTableExist("web_apps")); EXPECT_TRUE(connection.DoesTableExist("autofill")); EXPECT_TRUE(connection.DoesTableExist("autofill_dates")); EXPECT_TRUE(connection.DoesTableExist("autofill_profiles")); EXPECT_TRUE(connection.DoesTableExist("credit_cards")); EXPECT_TRUE(connection.DoesTableExist("token_service")); } } // Tests that the |credit_card| table gets added to the schema for a version 22 // database. TEST_F(WebDatabaseMigrationTest, MigrateVersion22ToCurrent) { // This schema is taken from a build prior to the addition of the // |credit_card| table. Version 22 of the schema. Contrast this with the // corrupt version below. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_22.sql"))); // Verify pre-conditions. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // No |credit_card| table prior to version 23. ASSERT_FALSE(connection.DoesColumnExist("credit_cards", "guid")); ASSERT_FALSE( connection.DoesColumnExist("credit_cards", "card_number_encrypted")); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // |credit_card| table now exists. EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "guid")); EXPECT_TRUE( connection.DoesColumnExist("credit_cards", "card_number_encrypted")); } } // Tests that the |credit_card| table gets added to the schema for a corrupt // version 22 database. The corruption is that the |credit_cards| table exists // but the schema version number was not set correctly to 23 or later. This // test exercises code introduced to fix bug http://crbug.com/50699 that // resulted from the corruption. TEST_F(WebDatabaseMigrationTest, MigrateVersion22CorruptedToCurrent) { // This schema is taken from a build after the addition of the |credit_card| // table. Due to a bug in the migration logic the version is set incorrectly // to 22 (it should have been updated to 23 at least). ASSERT_NO_FATAL_FAILURE( LoadDatabase(FILE_PATH_LITERAL("version_22_corrupt.sql"))); // Verify pre-conditions. These are expectations for corrupt version 22 of // the database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Columns existing and not existing before current version. ASSERT_TRUE(connection.DoesColumnExist("credit_cards", "unique_id")); ASSERT_TRUE( connection.DoesColumnExist("credit_cards", "card_number_encrypted")); ASSERT_TRUE(connection.DoesColumnExist("keywords", "id")); ASSERT_FALSE(connection.DoesColumnExist("keywords", "logo_id")); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // Columns existing and not existing before version 25. EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "unique_id")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "guid")); EXPECT_TRUE( connection.DoesColumnExist("credit_cards", "card_number_encrypted")); EXPECT_TRUE(connection.DoesColumnExist("keywords", "id")); EXPECT_TRUE(connection.DoesColumnExist("keywords", "logo_id")); } } // Tests that the |keywords| |logo_id| column gets added to the schema for a // version 24 database. TEST_F(WebDatabaseMigrationTest, MigrateVersion24ToCurrent) { // This schema is taken from a build prior to the addition of the |keywords| // |logo_id| column. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_24.sql"))); // Verify pre-conditions. These are expectations for version 24 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Columns existing and not existing before current version. ASSERT_TRUE(connection.DoesColumnExist("keywords", "id")); ASSERT_FALSE(connection.DoesColumnExist("keywords", "logo_id")); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // |keywords| |logo_id| column should have been added. EXPECT_TRUE(connection.DoesColumnExist("keywords", "id")); EXPECT_TRUE(connection.DoesColumnExist("keywords", "logo_id")); } } // Tests that the |keywords| |created_by_policy| column gets added to the schema // for a version 25 database. TEST_F(WebDatabaseMigrationTest, MigrateVersion25ToCurrent) { // This schema is taken from a build prior to the addition of the |keywords| // |created_by_policy| column. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_25.sql"))); // Verify pre-conditions. These are expectations for version 25 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // |keywords| |logo_id| column should have been added. EXPECT_TRUE(connection.DoesColumnExist("keywords", "id")); EXPECT_TRUE(connection.DoesColumnExist("keywords", "created_by_policy")); } } // Tests that the credit_cards.billing_address column is changed from a string // to an int whilst preserving the associated billing address. This version of // the test makes sure a stored label is converted to an ID. TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringLabels) { // This schema is taken from a build prior to the change of column type for // credit_cards.billing_address from string to int. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_26.sql"))); // Verify pre-conditions. These are expectations for version 26 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Columns existing and not existing before current version. EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "billing_address")); std::string stmt = "INSERT INTO autofill_profiles" "(label, unique_id, first_name, middle_name, last_name, email," " company_name, address_line_1, address_line_2, city, state, zipcode," " country, phone, fax)" "VALUES ('Home',1,'','','','','','','','','','','','','')"; sql::Statement s(connection.GetUniqueStatement(stmt.c_str())); ASSERT_TRUE(s.Run()); // Insert a CC linked to an existing address. std::string stmt2 = "INSERT INTO credit_cards" "(label, unique_id, name_on_card, type, card_number," " expiration_month, expiration_year, verification_code, billing_address," " shipping_address, card_number_encrypted, verification_code_encrypted)" "VALUES ('label',2,'Jack','Visa','1234',2,2012,'','Home','','','')"; sql::Statement s2(connection.GetUniqueStatement(stmt2.c_str())); ASSERT_TRUE(s2.Run()); // |billing_address| is a string. std::string stmt3 = "SELECT billing_address FROM credit_cards"; sql::Statement s3(connection.GetUniqueStatement(stmt3.c_str())); ASSERT_TRUE(s3.Step()); EXPECT_EQ(s3.ColumnType(0), sql::COLUMN_TYPE_TEXT); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "billing_address")); // Verify the credit card data is converted. sql::Statement s(connection.GetUniqueStatement( "SELECT guid, name_on_card, expiration_month, expiration_year, " "card_number_encrypted, date_modified " "FROM credit_cards")); ASSERT_TRUE(s.Step()); EXPECT_EQ("Jack", s.ColumnString(1)); EXPECT_EQ(2, s.ColumnInt(2)); EXPECT_EQ(2012, s.ColumnInt(3)); // Column 5 is encrypted number blob. // Column 6 is date_modified. } } // Tests that the credit_cards.billing_address column is changed from a string // to an int whilst preserving the associated billing address. This version of // the test makes sure a stored string ID is converted to an integer ID. TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringIDs) { // This schema is taken from a build prior to the change of column type for // credit_cards.billing_address from string to int. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_26.sql"))); // Verify pre-conditions. These are expectations for version 26 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "billing_address")); std::string stmt = "INSERT INTO autofill_profiles" "(label, unique_id, first_name, middle_name, last_name, email," " company_name, address_line_1, address_line_2, city, state, zipcode," " country, phone, fax)" "VALUES ('Home',1,'','','','','','','','','','','','','')"; sql::Statement s(connection.GetUniqueStatement(stmt.c_str())); ASSERT_TRUE(s.Run()); // Insert a CC linked to an existing address. std::string stmt2 = "INSERT INTO credit_cards" "(label, unique_id, name_on_card, type, card_number," " expiration_month, expiration_year, verification_code, billing_address," " shipping_address, card_number_encrypted, verification_code_encrypted)" "VALUES ('label',2,'Jack','Visa','1234',2,2012,'','1','','','')"; sql::Statement s2(connection.GetUniqueStatement(stmt2.c_str())); ASSERT_TRUE(s2.Run()); // |billing_address| is a string. std::string stmt3 = "SELECT billing_address FROM credit_cards"; sql::Statement s3(connection.GetUniqueStatement(stmt3.c_str())); ASSERT_TRUE(s3.Step()); EXPECT_EQ(s3.ColumnType(0), sql::COLUMN_TYPE_TEXT); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // |keywords| |logo_id| column should have been added. EXPECT_TRUE(connection.DoesColumnExist("keywords", "id")); EXPECT_TRUE(connection.DoesColumnExist("keywords", "created_by_policy")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "billing_address")); // Verify the credit card data is converted. sql::Statement s(connection.GetUniqueStatement( "SELECT guid, name_on_card, expiration_month, expiration_year, " "card_number_encrypted, date_modified " "FROM credit_cards")); ASSERT_TRUE(s.Step()); EXPECT_EQ("Jack", s.ColumnString(1)); EXPECT_EQ(2, s.ColumnInt(2)); EXPECT_EQ(2012, s.ColumnInt(3)); // Column 5 is encrypted credit card number blob. // Column 6 is date_modified. } } // Tests migration from 27->current. This test is now the same as 28->current // as the column added in 28 was nuked in 29. TEST_F(WebDatabaseMigrationTest, MigrateVersion27ToCurrent) { // Initialize the database. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_27.sql"))); // Verify pre-conditions. These are expectations for version 28 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); ASSERT_FALSE(connection.DoesColumnExist("keywords", "supports_instant")); ASSERT_FALSE(connection.DoesColumnExist("keywords", "instant_url")); } MigrateVersion28Assertions(); } // Makes sure instant_url is added correctly to keywords. TEST_F(WebDatabaseMigrationTest, MigrateVersion28ToCurrent) { // Initialize the database. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_28.sql"))); // Verify pre-conditions. These are expectations for version 28 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); ASSERT_TRUE(connection.DoesColumnExist("keywords", "supports_instant")); ASSERT_FALSE(connection.DoesColumnExist("keywords", "instant_url")); } MigrateVersion28Assertions(); } // Makes sure date_modified is added correctly to autofill_profiles and // credit_cards. TEST_F(WebDatabaseMigrationTest, MigrateVersion29ToCurrent) { // Initialize the database. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_29.sql"))); // Verify pre-conditions. These are expectations for version 29 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "date_modified")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "date_modified")); } // Load the database via the WebDatabase class and migrate the database to // the current version. Time pre_creation_time = Time::Now(); { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } Time post_creation_time = Time::Now(); // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // Check that the columns were created. EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "date_modified")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "date_modified")); sql::Statement s_profiles(connection.GetUniqueStatement( "SELECT date_modified FROM autofill_profiles ")); ASSERT_TRUE(s_profiles); while (s_profiles.Step()) { EXPECT_GE(s_profiles.ColumnInt64(0), pre_creation_time.ToTimeT()); EXPECT_LE(s_profiles.ColumnInt64(0), post_creation_time.ToTimeT()); } EXPECT_TRUE(s_profiles.Succeeded()); sql::Statement s_credit_cards(connection.GetUniqueStatement( "SELECT date_modified FROM credit_cards ")); ASSERT_TRUE(s_credit_cards); while (s_credit_cards.Step()) { EXPECT_GE(s_credit_cards.ColumnInt64(0), pre_creation_time.ToTimeT()); EXPECT_LE(s_credit_cards.ColumnInt64(0), post_creation_time.ToTimeT()); } EXPECT_TRUE(s_credit_cards.Succeeded()); } } // Makes sure guids are added to autofill_profiles and credit_cards tables. TEST_F(WebDatabaseMigrationTest, MigrateVersion30ToCurrent) { // Initialize the database. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_30.sql"))); // Verify pre-conditions. These are expectations for version 29 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "guid")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "guid")); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); ASSERT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid")); ASSERT_TRUE(connection.DoesColumnExist("credit_cards", "guid")); // Check that guids are non-null, non-empty, conforms to guid format, and // are different. sql::Statement s( connection.GetUniqueStatement("SELECT guid FROM autofill_profiles")); ASSERT_TRUE(s.Step()); std::string guid1 = s.ColumnString(0); EXPECT_TRUE(guid::IsValidGUID(guid1)); ASSERT_TRUE(s.Step()); std::string guid2 = s.ColumnString(0); EXPECT_TRUE(guid::IsValidGUID(guid2)); EXPECT_NE(guid1, guid2); } } // Removes unique IDs and make GUIDs the primary key. Also removes unused // columns. TEST_F(WebDatabaseMigrationTest, MigrateVersion31ToCurrent) { // Initialize the database. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_31.sql"))); // Verify pre-conditions. These are expectations for version 30 of the // database. AutofillProfile profile; string16 profile_label; int profile_unique_id = 0; int64 profile_date_modified = 0; CreditCard credit_card; string16 cc_label; int cc_unique_id = 0; std::string cc_number_encrypted; int64 cc_date_modified = 0; { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Verify existence of columns we'll be changing. EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "unique_id")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "guid")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "unique_id")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "type")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "card_number")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "verification_code")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "billing_address")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "shipping_address")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "verification_code_encrypted")); // Fetch data in the database prior to migration. sql::Statement s1( connection.GetUniqueStatement( "SELECT label, unique_id, first_name, middle_name, last_name, " "email, company_name, address_line_1, address_line_2, city, state, " "zipcode, country, phone, fax, date_modified, guid " "FROM autofill_profiles")); ASSERT_TRUE(s1.Step()); EXPECT_NO_FATAL_FAILURE(AutofillProfile31FromStatement( s1, &profile, &profile_label, &profile_unique_id, &profile_date_modified)); sql::Statement s2( connection.GetUniqueStatement( "SELECT label, unique_id, name_on_card, type, card_number, " "expiration_month, expiration_year, verification_code, " "billing_address, shipping_address, card_number_encrypted, " "verification_code_encrypted, date_modified, guid " "FROM credit_cards")); ASSERT_TRUE(s2.Step()); EXPECT_NO_FATAL_FAILURE(CreditCard31FromStatement(s2, &credit_card, &cc_label, &cc_unique_id, &cc_number_encrypted, &cc_date_modified)); EXPECT_NE(profile_unique_id, cc_unique_id); EXPECT_NE(profile.guid(), credit_card.guid()); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // Verify existence of columns we'll be changing. EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "unique_id")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "guid")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "unique_id")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "type")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "card_number")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "verification_code")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "billing_address")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "shipping_address")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "verification_code_encrypted")); // Verify data in the database after the migration. sql::Statement s1( connection.GetUniqueStatement( "SELECT guid, company_name, address_line_1, address_line_2, " "city, state, zipcode, country, date_modified " "FROM autofill_profiles")); ASSERT_TRUE(s1.Step()); AutofillProfile profile_a; int64 profile_date_modified_a = 0; EXPECT_NO_FATAL_FAILURE(AutofillProfile33FromStatement( s1, &profile_a, &profile_date_modified_a)); EXPECT_EQ(profile.guid(), profile_a.guid()); EXPECT_EQ(profile.GetInfo(COMPANY_NAME), profile_a.GetInfo(COMPANY_NAME)); EXPECT_EQ(profile.GetInfo(ADDRESS_HOME_LINE1), profile_a.GetInfo(ADDRESS_HOME_LINE1)); EXPECT_EQ(profile.GetInfo(ADDRESS_HOME_LINE2), profile_a.GetInfo(ADDRESS_HOME_LINE2)); EXPECT_EQ(profile.GetInfo(ADDRESS_HOME_CITY), profile_a.GetInfo(ADDRESS_HOME_CITY)); EXPECT_EQ(profile.GetInfo(ADDRESS_HOME_STATE), profile_a.GetInfo(ADDRESS_HOME_STATE)); EXPECT_EQ(profile.GetInfo(ADDRESS_HOME_ZIP), profile_a.GetInfo(ADDRESS_HOME_ZIP)); EXPECT_EQ(profile.GetInfo(ADDRESS_HOME_COUNTRY), profile_a.GetInfo(ADDRESS_HOME_COUNTRY)); EXPECT_EQ(profile_date_modified, profile_date_modified_a); sql::Statement s2( connection.GetUniqueStatement( "SELECT guid, name_on_card, expiration_month, " "expiration_year, card_number_encrypted, date_modified " "FROM credit_cards")); ASSERT_TRUE(s2.Step()); CreditCard credit_card_a; string16 cc_label_a; std::string cc_number_encrypted_a; int64 cc_date_modified_a = 0; EXPECT_NO_FATAL_FAILURE(CreditCard32FromStatement(s2, &credit_card_a, &cc_number_encrypted_a, &cc_date_modified_a)); EXPECT_EQ(credit_card, credit_card_a); EXPECT_EQ(cc_label, cc_label_a); EXPECT_EQ(cc_number_encrypted, cc_number_encrypted_a); EXPECT_EQ(cc_date_modified, cc_date_modified_a); } } // Factor |autofill_profiles| address information separately from name, email, // and phone. TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) { // Initialize the database. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_32.sql"))); // Verify pre-conditions. These are expectations for version 32 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Verify existence of columns we'll be changing. EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "label")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "first_name")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "middle_name")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "last_name")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "email")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "company_name")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "address_line_1")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "address_line_2")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "city")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "state")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "zipcode")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "country")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "phone")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "fax")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "date_modified")); EXPECT_FALSE(connection.DoesTableExist("autofill_profile_names")); EXPECT_FALSE(connection.DoesTableExist("autofill_profile_emails")); EXPECT_FALSE(connection.DoesTableExist("autofill_profile_phones")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "label")); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); // Verify changes to columns. EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "label")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "first_name")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "middle_name")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "last_name")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "email")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "company_name")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "address_line_1")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "address_line_2")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "city")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "state")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "zipcode")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "country")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "phone")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "fax")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "date_modified")); // New "names" table. EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_names", "guid")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_names", "first_name")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_names", "middle_name")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_names", "last_name")); // New "emails" table. EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_emails", "guid")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_emails", "email")); // New "phones" table. EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_phones", "guid")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_phones", "type")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_phones", "number")); EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "label")); // Verify data in the database after the migration. sql::Statement s1( connection.GetUniqueStatement( "SELECT guid, company_name, address_line_1, address_line_2, " "city, state, zipcode, country, date_modified " "FROM autofill_profiles")); // John Doe. ASSERT_TRUE(s1.Step()); EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s1.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16("Doe Enterprises"), s1.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16("1 Main St"), s1.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16("Apt 1"), s1.ColumnString16(3)); EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(4)); EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5)); EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(6)); EXPECT_EQ(ASCIIToUTF16("United States"), s1.ColumnString16(7)); EXPECT_EQ(1297882100L, s1.ColumnInt64(8)); // John P. Doe. // Gets merged during migration from 35 to 37 due to multi-valued fields. // Dave Smith. ASSERT_TRUE(s1.Step()); EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s1.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16("2 Main Street"), s1.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(3)); EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(4)); EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5)); EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(6)); EXPECT_EQ(ASCIIToUTF16("United States"), s1.ColumnString16(7)); EXPECT_EQ(1297882100L, s1.ColumnInt64(8)); // Dave Smith (Part 2). ASSERT_TRUE(s1.Step()); EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s1.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16("2 Main St"), s1.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(3)); EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(4)); EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5)); EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(6)); EXPECT_EQ(ASCIIToUTF16("United States"), s1.ColumnString16(7)); EXPECT_EQ(1297882100L, s1.ColumnInt64(8)); // Alfred E Newman. // Gets culled during migration from 35 to 36 due to incomplete address. // 3 Main St. ASSERT_TRUE(s1.Step()); EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s1.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16("3 Main St"), s1.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(3)); EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(4)); EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5)); EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(6)); EXPECT_EQ(ASCIIToUTF16("United States"), s1.ColumnString16(7)); EXPECT_EQ(1297882100L, s1.ColumnInt64(8)); // That should be all. EXPECT_FALSE(s1.Step()); sql::Statement s2( connection.GetUniqueStatement( "SELECT guid, first_name, middle_name, last_name " "FROM autofill_profile_names")); // John Doe. ASSERT_TRUE(s2.Step()); EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s2.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16("John"), s2.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16("Doe"), s2.ColumnString16(3)); // John P. Doe. Note same guid as above due to merging of multi-valued // fields. ASSERT_TRUE(s2.Step()); EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s2.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16("John"), s2.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16("P."), s2.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16("Doe"), s2.ColumnString16(3)); // Dave Smith. ASSERT_TRUE(s2.Step()); EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s2.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16("Dave"), s2.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16("Smith"), s2.ColumnString16(3)); // Dave Smith (Part 2). ASSERT_TRUE(s2.Step()); EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s2.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16("Dave"), s2.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16("Smith"), s2.ColumnString16(3)); // Alfred E Newman. // Gets culled during migration from 35 to 36 due to incomplete address. // 3 Main St. ASSERT_TRUE(s2.Step()); EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s2.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(3)); // Should be all. EXPECT_FALSE(s2.Step()); sql::Statement s3( connection.GetUniqueStatement( "SELECT guid, email " "FROM autofill_profile_emails")); // John Doe. ASSERT_TRUE(s3.Step()); EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s3.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16("john@doe.com"), s3.ColumnString16(1)); // John P. Doe. // Gets culled during migration from 35 to 37 due to merging of John Doe and // John P. Doe addresses. // 2 Main Street. ASSERT_TRUE(s3.Step()); EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s3.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16(""), s3.ColumnString16(1)); // 2 Main St. ASSERT_TRUE(s3.Step()); EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s3.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16(""), s3.ColumnString16(1)); // Alfred E Newman. // Gets culled during migration from 35 to 36 due to incomplete address. // 3 Main St. ASSERT_TRUE(s3.Step()); EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s3.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16(""), s3.ColumnString16(1)); // Should be all. EXPECT_FALSE(s3.Step()); sql::Statement s4( connection.GetUniqueStatement( "SELECT guid, type, number " "FROM autofill_profile_phones")); // John Doe phone. ASSERT_TRUE(s4.Step()); EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s4.ColumnString(0)); EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone. EXPECT_EQ(ASCIIToUTF16("4151112222"), s4.ColumnString16(2)); // John Doe fax. ASSERT_TRUE(s4.Step()); EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s4.ColumnString(0)); EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means phone. EXPECT_EQ(ASCIIToUTF16("4153334444"), s4.ColumnString16(2)); // John P. Doe phone. // Gets culled during migration from 35 to 37 due to merging of John Doe and // John P. Doe addresses. // John P. Doe fax. // Gets culled during migration from 35 to 37 due to merging of John Doe and // John P. Doe addresses. // 2 Main Street phone. ASSERT_TRUE(s4.Step()); EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s4.ColumnString(0)); EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone. EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2)); // 2 Main Street fax. ASSERT_TRUE(s4.Step()); EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s4.ColumnString(0)); EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax. EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2)); // 2 Main St phone. ASSERT_TRUE(s4.Step()); EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s4.ColumnString(0)); EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone. EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2)); // 2 Main St fax. ASSERT_TRUE(s4.Step()); EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s4.ColumnString(0)); EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax. EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2)); // Note no phone or fax for Alfred E Newman. // 3 Main St phone. ASSERT_TRUE(s4.Step()); EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s4.ColumnString(0)); EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone. EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2)); // 2 Main St fax. ASSERT_TRUE(s4.Step()); EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s4.ColumnString(0)); EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax. EXPECT_EQ(ASCIIToUTF16(""), s4.ColumnString16(2)); // Should be all. EXPECT_FALSE(s4.Step()); } } // Adds a column for the autofill profile's country code. TEST_F(WebDatabaseMigrationTest, MigrateVersion33ToCurrent) { // Initialize the database. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_33.sql"))); // Verify pre-conditions. These are expectations for version 33 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "country_code")); // Check that the country value is the one we expect. sql::Statement s( connection.GetUniqueStatement("SELECT country FROM autofill_profiles")); ASSERT_TRUE(s.Step()); std::string country = s.ColumnString(0); EXPECT_EQ("United States", country); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); ASSERT_TRUE(connection.DoesColumnExist("autofill_profiles", "country_code")); // Check that the country code is properly converted. sql::Statement s(connection.GetUniqueStatement( "SELECT country_code FROM autofill_profiles")); ASSERT_TRUE(s.Step()); std::string country_code = s.ColumnString(0); EXPECT_EQ("US", country_code); } } // Cleans up bad country code "UK" in favor of good country code "GB". TEST_F(WebDatabaseMigrationTest, MigrateVersion34ToCurrent) { // Initialize the database. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_34.sql"))); // Verify pre-conditions. These are expectations for version 34 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "country_code")); // Check that the country_code value is the one we expect. sql::Statement s( connection.GetUniqueStatement("SELECT country_code " "FROM autofill_profiles")); ASSERT_TRUE(s.Step()); std::string country_code = s.ColumnString(0); EXPECT_EQ("UK", country_code); // Should have only one. ASSERT_FALSE(s.Step()); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); ASSERT_TRUE(connection.DoesColumnExist("autofill_profiles", "country_code")); // Check that the country_code code is properly converted. sql::Statement s(connection.GetUniqueStatement( "SELECT country_code FROM autofill_profiles")); ASSERT_TRUE(s.Step()); std::string country_code = s.ColumnString(0); EXPECT_EQ("GB", country_code); // Should have only one. ASSERT_FALSE(s.Step()); } } // Cleans up invalid profiles based on more agressive merging. Filters out // profiles that are subsets of other profiles, and profiles with invalid email, // state, and incomplete address. TEST_F(WebDatabaseMigrationTest, MigrateVersion35ToCurrent) { // Initialize the database. ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_35.sql"))); // Verify pre-conditions. These are expectations for version 34 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); EXPECT_FALSE(connection.DoesTableExist("autofill_profiles_trash")); ASSERT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid")); // Check that there are 6 profiles prior to merge. sql::Statement s( connection.GetUniqueStatement("SELECT guid FROM autofill_profiles")); int i = 0; while (s.Step()) ++i; EXPECT_EQ(6, i); } // Load the database via the WebDatabase class and migrate the database to // the current version. { WebDatabase db; ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); } // Verify post-conditions. These are expectations for current version of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Check version. EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); ASSERT_TRUE(connection.DoesTableExist("autofill_profiles_trash")); ASSERT_TRUE(connection.DoesColumnExist("autofill_profiles_trash", "guid")); ASSERT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid")); // Verify data in the database after the migration. sql::Statement s1( connection.GetUniqueStatement( "SELECT guid, company_name, address_line_1, address_line_2, " "city, state, zipcode, country, date_modified " "FROM autofill_profiles")); // John Doe. ASSERT_TRUE(s1.Step()); EXPECT_EQ("00000000-0000-0000-0000-000000000001", s1.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16("Acme Inc."), s1.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16("1 Main Street"), s1.ColumnString16(2)); EXPECT_EQ(ASCIIToUTF16("Apt 2"), s1.ColumnString16(3)); EXPECT_EQ(ASCIIToUTF16("San Francisco"), s1.ColumnString16(4)); EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5)); EXPECT_EQ(ASCIIToUTF16("94102"), s1.ColumnString16(6)); EXPECT_EQ(ASCIIToUTF16("United States"), s1.ColumnString16(7)); EXPECT_EQ(1300131704, s1.ColumnInt64(8)); // That should be it. ASSERT_FALSE(s1.Step()); // Check that there 5 trashed profile after the merge. sql::Statement s2( connection.GetUniqueStatement("SELECT guid " "FROM autofill_profiles_trash")); ASSERT_TRUE(s2.Step()); EXPECT_EQ("00000000-0000-0000-0000-000000000002", s2.ColumnString(0)); ASSERT_TRUE(s2.Step()); EXPECT_EQ("00000000-0000-0000-0000-000000000003", s2.ColumnString(0)); ASSERT_TRUE(s2.Step()); EXPECT_EQ("00000000-0000-0000-0000-000000000004", s2.ColumnString(0)); ASSERT_TRUE(s2.Step()); EXPECT_EQ("00000000-0000-0000-0000-000000000005", s2.ColumnString(0)); ASSERT_TRUE(s2.Step()); EXPECT_EQ("00000000-0000-0000-0000-000000000006", s2.ColumnString(0)); // That should be it. ASSERT_FALSE(s2.Step()); } }