1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/scoped_temp_dir.h" 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h" 112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/syncable_file_system_util.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/external_mount_points.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_util.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/db.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define FPL FILE_PATH_LITERAL 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace sync_file_system { 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace drive_backend { 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace { 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void VerifyKeyAndValue(const std::string& key, 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& expect_val, 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) leveldb::DB* db) { 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions())); 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) itr->Seek(key); 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(itr->Valid()); 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(expect_val, itr->value().ToString()); 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void VerifyNotExist(const std::string& key, leveldb::DB* db) { 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions())); 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) itr->Seek(key); 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_TRUE(!itr->Valid() || 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) !StartsWithASCII(itr->key().ToString(), key, true)); 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST(DriveMetadataDBMigrationUtilTest, RollbackFromV4ToV3) { 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Rollback from version 4 to version 3. 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Please see metadata_database_index.cc for version 3 format, and 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // metadata_database_index_on_disk.cc for version 4 format. 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kDatabaseVersionKey[] = "VERSION"; 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kServiceMetadataKey[] = "SERVICE"; 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kFileMetadataKeyPrefix[] = "FILE: "; 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kFileTrackerKeyPrefix[] = "TRACKER: "; 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Key prefixes used in version 4. 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kAppRootIDByAppIDKeyPrefix[] = "APP_ROOT: "; 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kActiveTrackerIDByFileIDKeyPrefix[] = "ACTIVE_FILE: "; 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kTrackerIDByFileIDKeyPrefix[] = "TRACKER_FILE: "; 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kMultiTrackerByFileIDKeyPrefix[] = "MULTI_FILE: "; 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kActiveTrackerIDByParentAndTitleKeyPrefix[] = "ACTIVE_PATH: "; 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kTrackerIDByParentAndTitleKeyPrefix[] = "TRACKER_PATH: "; 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kMultiBackingParentAndTitleKeyPrefix[] = "MULTI_PATH: "; 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kDirtyIDKeyPrefix[] = "DIRTY: "; 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char kDemotedDirtyIDKeyPrefix[] = "DEMOTED_DIRTY: "; 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Set up environment. 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) leveldb::DB* db_ptr = NULL; 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::ScopedTempDir base_dir; 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ASSERT_TRUE(base_dir.CreateUniqueTempDir()); 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) leveldb::Options options; 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) options.create_if_missing = true; 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string db_dir = 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) storage::FilePathToString(base_dir.path().Append(kDatabaseName)); 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) leveldb::Status status = leveldb::DB::Open(options, db_dir, &db_ptr); 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_TRUE(status.ok()); 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<leveldb::DB> db(db_ptr); 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Setup the database with the schema version 4, without IDs. 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) leveldb::WriteBatch batch; 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kDatabaseVersionKey, "4"); 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kServiceMetadataKey, "service_metadata"); 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kFileMetadataKeyPrefix, "file_metadata"); 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kFileTrackerKeyPrefix, "file_tracker"); 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kAppRootIDByAppIDKeyPrefix, "app_root_id"); 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kActiveTrackerIDByFileIDKeyPrefix, "active_id_by_file"); 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kTrackerIDByFileIDKeyPrefix, "tracker_id_by_file"); 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kMultiTrackerByFileIDKeyPrefix, "multi_tracker_by_file"); 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kActiveTrackerIDByParentAndTitleKeyPrefix, "active_id_by_path"); 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kTrackerIDByParentAndTitleKeyPrefix, "tracker_id_by_path"); 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kMultiBackingParentAndTitleKeyPrefix, "multi_tracker_by_path"); 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kDirtyIDKeyPrefix, "dirty"); 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) batch.Put(kDemotedDirtyIDKeyPrefix, "demoted_dirty"); 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) leveldb::Status status = db->Write(leveldb::WriteOptions(), &batch); 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, LevelDBStatusToSyncStatusCode(status)); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Migrate the database. 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MigrateDatabaseFromV4ToV3(db.get()); 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Verify DB schema verison 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyKeyAndValue(kDatabaseVersionKey, "3", db.get()); 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Verify remained entries. 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyKeyAndValue(kServiceMetadataKey, "service_metadata", db.get()); 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyKeyAndValue(kFileMetadataKeyPrefix, "file_metadata", db.get()); 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyKeyAndValue(kFileTrackerKeyPrefix, "file_tracker", db.get()); 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Verify 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyNotExist(kAppRootIDByAppIDKeyPrefix, db.get()); 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyNotExist(kActiveTrackerIDByFileIDKeyPrefix, db.get()); 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyNotExist(kTrackerIDByFileIDKeyPrefix, db.get()); 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyNotExist(kMultiTrackerByFileIDKeyPrefix, db.get()); 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyNotExist(kActiveTrackerIDByParentAndTitleKeyPrefix, db.get()); 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyNotExist(kTrackerIDByParentAndTitleKeyPrefix, db.get()); 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyNotExist(kMultiBackingParentAndTitleKeyPrefix, db.get()); 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyNotExist(kDirtyIDKeyPrefix, db.get()); 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VerifyNotExist(kDemotedDirtyIDKeyPrefix, db.get()); 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace drive_backend 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace sync_file_system 125