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 "net/disk_cache/simple/simple_version_upgrade.h" 6 7 #include "base/basictypes.h" 8 #include "base/file_util.h" 9 #include "base/files/file_path.h" 10 #include "base/files/scoped_temp_dir.h" 11 #include "base/format_macros.h" 12 #include "base/strings/stringprintf.h" 13 #include "net/base/net_errors.h" 14 #include "net/disk_cache/simple/simple_backend_version.h" 15 #include "net/disk_cache/simple/simple_entry_format_history.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 // The migration process relies on ability to rename newly created files, which 19 // could be problematic on Windows XP. 20 #if defined(OS_POSIX) 21 22 namespace { 23 24 // Same as |disk_cache::kSimpleInitialMagicNumber|. 25 const uint64 kSimpleInitialMagicNumber = GG_UINT64_C(0xfcfb6d1ba7725c30); 26 27 // The "fake index" file that cache backends use to distinguish whether the 28 // cache belongs to one backend or another. 29 const char kFakeIndexFileName[] = "index"; 30 31 // Same as |SimpleIndexFile::kIndexFileName|. 32 const char kIndexFileName[] = "the-real-index"; 33 34 bool WriteFakeIndexFileV5(const base::FilePath& cache_path) { 35 disk_cache::FakeIndexData data; 36 data.version = 5; 37 data.initial_magic_number = kSimpleInitialMagicNumber; 38 data.unused_must_be_zero1 = 0; 39 data.unused_must_be_zero2 = 0; 40 const base::FilePath file_name = cache_path.AppendASCII("index"); 41 return sizeof(data) == 42 base::WriteFile( 43 file_name, reinterpret_cast<const char*>(&data), sizeof(data)); 44 } 45 46 TEST(SimpleVersionUpgradeTest, FailsToMigrateBackwards) { 47 base::ScopedTempDir cache_dir; 48 ASSERT_TRUE(cache_dir.CreateUniqueTempDir()); 49 const base::FilePath cache_path = cache_dir.path(); 50 51 disk_cache::FakeIndexData data; 52 data.version = 100500; 53 data.initial_magic_number = kSimpleInitialMagicNumber; 54 data.unused_must_be_zero1 = 0; 55 data.unused_must_be_zero2 = 0; 56 const base::FilePath file_name = cache_path.AppendASCII(kFakeIndexFileName); 57 ASSERT_EQ(implicit_cast<int>(sizeof(data)), 58 base::WriteFile( 59 file_name, reinterpret_cast<const char*>(&data), sizeof(data))); 60 EXPECT_FALSE(disk_cache::UpgradeSimpleCacheOnDisk(cache_dir.path())); 61 } 62 63 TEST(SimpleVersionUpgradeTest, FakeIndexVersionGetsUpdated) { 64 base::ScopedTempDir cache_dir; 65 ASSERT_TRUE(cache_dir.CreateUniqueTempDir()); 66 const base::FilePath cache_path = cache_dir.path(); 67 68 WriteFakeIndexFileV5(cache_path); 69 const std::string file_contents("incorrectly serialized data"); 70 const base::FilePath index_file = cache_path.AppendASCII(kIndexFileName); 71 ASSERT_EQ(implicit_cast<int>(file_contents.size()), 72 base::WriteFile( 73 index_file, file_contents.data(), file_contents.size())); 74 75 // Upgrade. 76 ASSERT_TRUE(disk_cache::UpgradeSimpleCacheOnDisk(cache_path)); 77 78 // Check that the version in the fake index file is updated. 79 std::string new_fake_index_contents; 80 ASSERT_TRUE(base::ReadFileToString(cache_path.AppendASCII(kFakeIndexFileName), 81 &new_fake_index_contents)); 82 const disk_cache::FakeIndexData* fake_index_header; 83 EXPECT_EQ(sizeof(*fake_index_header), new_fake_index_contents.size()); 84 fake_index_header = reinterpret_cast<const disk_cache::FakeIndexData*>( 85 new_fake_index_contents.data()); 86 EXPECT_EQ(disk_cache::kSimpleVersion, fake_index_header->version); 87 EXPECT_EQ(kSimpleInitialMagicNumber, fake_index_header->initial_magic_number); 88 } 89 90 TEST(SimpleVersionUpgradeTest, UpgradeV5V6IndexMustDisappear) { 91 base::ScopedTempDir cache_dir; 92 ASSERT_TRUE(cache_dir.CreateUniqueTempDir()); 93 const base::FilePath cache_path = cache_dir.path(); 94 95 WriteFakeIndexFileV5(cache_path); 96 const std::string file_contents("incorrectly serialized data"); 97 const base::FilePath index_file = cache_path.AppendASCII(kIndexFileName); 98 ASSERT_EQ(implicit_cast<int>(file_contents.size()), 99 base::WriteFile( 100 index_file, file_contents.data(), file_contents.size())); 101 102 // Create a few entry-like files. 103 const uint64 kEntries = 5; 104 for (uint64 entry_hash = 0; entry_hash < kEntries; ++entry_hash) { 105 for (int index = 0; index < 3; ++index) { 106 std::string file_name = 107 base::StringPrintf("%016" PRIx64 "_%1d", entry_hash, index); 108 std::string entry_contents = 109 file_contents + 110 base::StringPrintf(" %" PRIx64, implicit_cast<uint64>(entry_hash)); 111 ASSERT_EQ(implicit_cast<int>(entry_contents.size()), 112 base::WriteFile(cache_path.AppendASCII(file_name), 113 entry_contents.data(), 114 entry_contents.size())); 115 } 116 } 117 118 // Upgrade. 119 ASSERT_TRUE(disk_cache::UpgradeIndexV5V6(cache_path)); 120 121 // Check that the old index disappeared but the files remain unchanged. 122 EXPECT_FALSE(base::PathExists(index_file)); 123 for (uint64 entry_hash = 0; entry_hash < kEntries; ++entry_hash) { 124 for (int index = 0; index < 3; ++index) { 125 std::string file_name = 126 base::StringPrintf("%016" PRIx64 "_%1d", entry_hash, index); 127 std::string expected_contents = 128 file_contents + 129 base::StringPrintf(" %" PRIx64, implicit_cast<uint64>(entry_hash)); 130 std::string real_contents; 131 EXPECT_TRUE(base::ReadFileToString(cache_path.AppendASCII(file_name), 132 &real_contents)); 133 EXPECT_EQ(expected_contents, real_contents); 134 } 135 } 136 } 137 138 } // namespace 139 140 #endif // defined(OS_POSIX) 141