1// Copyright 2013 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 "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h"
6
7#include "base/files/scoped_temp_dir.h"
8#include "base/strings/string_number_conversions.h"
9#include "base/strings/string_util.h"
10#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
11#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
12#include "storage/browser/fileapi/external_mount_points.h"
13#include "storage/common/fileapi/file_system_util.h"
14#include "testing/gtest/include/gtest/gtest.h"
15#include "third_party/leveldatabase/src/include/leveldb/db.h"
16#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
17#include "url/gurl.h"
18
19#define FPL FILE_PATH_LITERAL
20
21namespace sync_file_system {
22namespace drive_backend {
23
24namespace {
25
26void VerifyKeyAndValue(const std::string& key,
27                       const std::string& expect_val,
28                       leveldb::DB* db) {
29  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
30
31  itr->Seek(key);
32  EXPECT_TRUE(itr->Valid());
33  EXPECT_EQ(expect_val, itr->value().ToString());
34}
35
36void VerifyNotExist(const std::string& key, leveldb::DB* db) {
37  scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions()));
38
39  itr->Seek(key);
40  EXPECT_TRUE(!itr->Valid() ||
41              !StartsWithASCII(itr->key().ToString(), key, true));
42}
43
44}  // namespace
45
46TEST(DriveMetadataDBMigrationUtilTest, RollbackFromV4ToV3) {
47  // Rollback from version 4 to version 3.
48  // Please see metadata_database_index.cc for version 3 format, and
49  // metadata_database_index_on_disk.cc for version 4 format.
50
51  const char kDatabaseVersionKey[] = "VERSION";
52  const char kServiceMetadataKey[] = "SERVICE";
53  const char kFileMetadataKeyPrefix[] = "FILE: ";
54  const char kFileTrackerKeyPrefix[] = "TRACKER: ";
55
56  // Key prefixes used in version 4.
57  const char kAppRootIDByAppIDKeyPrefix[] = "APP_ROOT: ";
58  const char kActiveTrackerIDByFileIDKeyPrefix[] = "ACTIVE_FILE: ";
59  const char kTrackerIDByFileIDKeyPrefix[] = "TRACKER_FILE: ";
60  const char kMultiTrackerByFileIDKeyPrefix[] = "MULTI_FILE: ";
61  const char kActiveTrackerIDByParentAndTitleKeyPrefix[] = "ACTIVE_PATH: ";
62  const char kTrackerIDByParentAndTitleKeyPrefix[] = "TRACKER_PATH: ";
63  const char kMultiBackingParentAndTitleKeyPrefix[] = "MULTI_PATH: ";
64  const char kDirtyIDKeyPrefix[] = "DIRTY: ";
65  const char kDemotedDirtyIDKeyPrefix[] = "DEMOTED_DIRTY: ";
66
67  // Set up environment.
68  leveldb::DB* db_ptr = NULL;
69  base::ScopedTempDir base_dir;
70  ASSERT_TRUE(base_dir.CreateUniqueTempDir());
71  {
72    leveldb::Options options;
73    options.create_if_missing = true;
74    std::string db_dir =
75        storage::FilePathToString(base_dir.path().Append(kDatabaseName));
76    leveldb::Status status = leveldb::DB::Open(options, db_dir, &db_ptr);
77    ASSERT_TRUE(status.ok());
78  }
79  scoped_ptr<leveldb::DB> db(db_ptr);
80
81  // Setup the database with the schema version 4, without IDs.
82  leveldb::WriteBatch batch;
83  batch.Put(kDatabaseVersionKey, "4");
84  batch.Put(kServiceMetadataKey, "service_metadata");
85  batch.Put(kFileMetadataKeyPrefix, "file_metadata");
86  batch.Put(kFileTrackerKeyPrefix, "file_tracker");
87  batch.Put(kAppRootIDByAppIDKeyPrefix, "app_root_id");
88  batch.Put(kActiveTrackerIDByFileIDKeyPrefix, "active_id_by_file");
89  batch.Put(kTrackerIDByFileIDKeyPrefix, "tracker_id_by_file");
90  batch.Put(kMultiTrackerByFileIDKeyPrefix, "multi_tracker_by_file");
91  batch.Put(kActiveTrackerIDByParentAndTitleKeyPrefix, "active_id_by_path");
92  batch.Put(kTrackerIDByParentAndTitleKeyPrefix, "tracker_id_by_path");
93  batch.Put(kMultiBackingParentAndTitleKeyPrefix, "multi_tracker_by_path");
94  batch.Put(kDirtyIDKeyPrefix, "dirty");
95  batch.Put(kDemotedDirtyIDKeyPrefix, "demoted_dirty");
96
97  leveldb::Status status = db->Write(leveldb::WriteOptions(), &batch);
98  EXPECT_EQ(SYNC_STATUS_OK, LevelDBStatusToSyncStatusCode(status));
99
100  // Migrate the database.
101  MigrateDatabaseFromV4ToV3(db.get());
102
103  // Verify DB schema verison
104  VerifyKeyAndValue(kDatabaseVersionKey, "3", db.get());
105
106  // Verify remained entries.
107  VerifyKeyAndValue(kServiceMetadataKey, "service_metadata", db.get());
108  VerifyKeyAndValue(kFileMetadataKeyPrefix, "file_metadata", db.get());
109  VerifyKeyAndValue(kFileTrackerKeyPrefix, "file_tracker", db.get());
110
111  // Verify
112  VerifyNotExist(kAppRootIDByAppIDKeyPrefix, db.get());
113  VerifyNotExist(kActiveTrackerIDByFileIDKeyPrefix, db.get());
114  VerifyNotExist(kTrackerIDByFileIDKeyPrefix, db.get());
115  VerifyNotExist(kMultiTrackerByFileIDKeyPrefix, db.get());
116  VerifyNotExist(kActiveTrackerIDByParentAndTitleKeyPrefix, db.get());
117  VerifyNotExist(kTrackerIDByParentAndTitleKeyPrefix, db.get());
118  VerifyNotExist(kMultiBackingParentAndTitleKeyPrefix, db.get());
119  VerifyNotExist(kDirtyIDKeyPrefix, db.get());
120  VerifyNotExist(kDemotedDirtyIDKeyPrefix, db.get());
121}
122
123}  // namespace drive_backend
124}  // namespace sync_file_system
125