block_files_unittest.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2006-2008 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 "base/file_util.h" 6#include "net/disk_cache/block_files.h" 7#include "net/disk_cache/disk_cache.h" 8#include "net/disk_cache/disk_cache_test_base.h" 9#include "net/disk_cache/disk_cache_test_util.h" 10#include "testing/gtest/include/gtest/gtest.h" 11 12using base::Time; 13 14namespace { 15 16// Returns the number of files in this folder. 17int NumberOfFiles(const FilePath& path) { 18 file_util::FileEnumerator iter(path, false, file_util::FileEnumerator::FILES); 19 int count = 0; 20 for (FilePath file = iter.Next(); !file.value().empty(); file = iter.Next()) { 21 count++; 22 } 23 return count; 24} 25 26} // namespace; 27 28namespace disk_cache { 29 30TEST_F(DiskCacheTest, BlockFiles_Grow) { 31 FilePath path = GetCacheFilePath(); 32 ASSERT_TRUE(DeleteCache(path)); 33 ASSERT_TRUE(file_util::CreateDirectory(path)); 34 35 BlockFiles files(path); 36 ASSERT_TRUE(files.Init(true)); 37 38 const int kMaxSize = 35000; 39 Addr address[kMaxSize]; 40 41 // Fill up the 32-byte block file (use three files). 42 for (int i = 0; i < kMaxSize; i++) { 43 EXPECT_TRUE(files.CreateBlock(RANKINGS, 4, &address[i])); 44 } 45 EXPECT_EQ(6, NumberOfFiles(path)); 46 47 // Make sure we don't keep adding files. 48 for (int i = 0; i < kMaxSize * 4; i += 2) { 49 int target = i % kMaxSize; 50 files.DeleteBlock(address[target], false); 51 EXPECT_TRUE(files.CreateBlock(RANKINGS, 4, &address[target])); 52 } 53 EXPECT_EQ(6, NumberOfFiles(path)); 54} 55 56// We should be able to delete empty block files. 57TEST_F(DiskCacheTest, BlockFiles_Shrink) { 58 FilePath path = GetCacheFilePath(); 59 ASSERT_TRUE(DeleteCache(path)); 60 ASSERT_TRUE(file_util::CreateDirectory(path)); 61 62 BlockFiles files(path); 63 ASSERT_TRUE(files.Init(true)); 64 65 const int kMaxSize = 35000; 66 Addr address[kMaxSize]; 67 68 // Fill up the 32-byte block file (use three files). 69 for (int i = 0; i < kMaxSize; i++) { 70 EXPECT_TRUE(files.CreateBlock(RANKINGS, 4, &address[i])); 71 } 72 73 // Now delete all the blocks, so that we can delete the two extra files. 74 for (int i = 0; i < kMaxSize; i++) { 75 files.DeleteBlock(address[i], false); 76 } 77 EXPECT_EQ(4, NumberOfFiles(path)); 78} 79 80// Handling of block files not properly closed. 81TEST_F(DiskCacheTest, BlockFiles_Recover) { 82 FilePath path = GetCacheFilePath(); 83 ASSERT_TRUE(DeleteCache(path)); 84 ASSERT_TRUE(file_util::CreateDirectory(path)); 85 86 BlockFiles files(path); 87 ASSERT_TRUE(files.Init(true)); 88 89 const int kNumEntries = 2000; 90 CacheAddr entries[kNumEntries]; 91 92 int seed = static_cast<int>(Time::Now().ToInternalValue()); 93 srand(seed); 94 for (int i = 0; i < kNumEntries; i++) { 95 Addr address(0); 96 int size = (rand() % 4) + 1; 97 EXPECT_TRUE(files.CreateBlock(RANKINGS, size, &address)); 98 entries[i] = address.value(); 99 } 100 101 for (int i = 0; i < kNumEntries; i++) { 102 int source1 = rand() % kNumEntries; 103 int source2 = rand() % kNumEntries; 104 CacheAddr temp = entries[source1]; 105 entries[source1] = entries[source2]; 106 entries[source2] = temp; 107 } 108 109 for (int i = 0; i < kNumEntries / 2; i++) { 110 Addr address(entries[i]); 111 files.DeleteBlock(address, false); 112 } 113 114 // At this point, there are kNumEntries / 2 entries on the file, randomly 115 // distributed both on location and size. 116 117 Addr address(entries[kNumEntries / 2]); 118 MappedFile* file = files.GetFile(address); 119 ASSERT_TRUE(NULL != file); 120 121 BlockFileHeader* header = 122 reinterpret_cast<BlockFileHeader*>(file->buffer()); 123 ASSERT_TRUE(NULL != header); 124 125 ASSERT_EQ(0, header->updating); 126 127 int max_entries = header->max_entries; 128 int empty_1 = header->empty[0]; 129 int empty_2 = header->empty[1]; 130 int empty_3 = header->empty[2]; 131 int empty_4 = header->empty[3]; 132 133 // Corrupt the file. 134 header->max_entries = header->empty[0] = 0; 135 header->empty[1] = header->empty[2] = header->empty[3] = 0; 136 header->updating = -1; 137 138 files.CloseFiles(); 139 140 ASSERT_TRUE(files.Init(false)); 141 142 // The file must have been fixed. 143 file = files.GetFile(address); 144 ASSERT_TRUE(NULL != file); 145 146 header = reinterpret_cast<BlockFileHeader*>(file->buffer()); 147 ASSERT_TRUE(NULL != header); 148 149 ASSERT_EQ(0, header->updating); 150 151 EXPECT_EQ(max_entries, header->max_entries); 152 EXPECT_EQ(empty_1, header->empty[0]); 153 EXPECT_EQ(empty_2, header->empty[1]); 154 EXPECT_EQ(empty_3, header->empty[2]); 155 EXPECT_EQ(empty_4, header->empty[3]); 156} 157 158// Handling of truncated files. 159TEST_F(DiskCacheTest, BlockFiles_ZeroSizeFile) { 160 FilePath path = GetCacheFilePath(); 161 ASSERT_TRUE(DeleteCache(path)); 162 ASSERT_TRUE(file_util::CreateDirectory(path)); 163 164 BlockFiles files(path); 165 ASSERT_TRUE(files.Init(true)); 166 167 FilePath filename = files.Name(0); 168 files.CloseFiles(); 169 // Truncate one of the files. 170 { 171 scoped_refptr<File> file(new File); 172 ASSERT_TRUE(file->Init(filename)); 173 EXPECT_TRUE(file->SetLength(0)); 174 } 175 176 // Initializing should fail, not crash. 177 ASSERT_FALSE(files.Init(false)); 178} 179 180// An invalid file can be detected after init. 181TEST_F(DiskCacheTest, BlockFiles_InvalidFile) { 182 FilePath path = GetCacheFilePath(); 183 ASSERT_TRUE(DeleteCache(path)); 184 ASSERT_TRUE(file_util::CreateDirectory(path)); 185 186 BlockFiles files(path); 187 ASSERT_TRUE(files.Init(true)); 188 189 // Let's access block 10 of file 5. (There is no file). 190 Addr addr(BLOCK_256, 1, 5, 10); 191 EXPECT_TRUE(NULL == files.GetFile(addr)); 192 193 // Let's create an invalid file. 194 FilePath filename(files.Name(5)); 195 char header[kBlockHeaderSize]; 196 memset(header, 'a', kBlockHeaderSize); 197 EXPECT_EQ(kBlockHeaderSize, 198 file_util::WriteFile(filename, header, kBlockHeaderSize)); 199 200 EXPECT_TRUE(NULL == files.GetFile(addr)); 201 202 // The file should not have been cached (it is still invalid). 203 EXPECT_TRUE(NULL == files.GetFile(addr)); 204} 205 206// Tests that we generate the correct file stats. 207TEST_F(DiskCacheTest, BlockFiles_Stats) { 208 ASSERT_TRUE(CopyTestCache("remove_load1")); 209 FilePath path = GetCacheFilePath(); 210 211 BlockFiles files(path); 212 ASSERT_TRUE(files.Init(false)); 213 int used, load; 214 215 files.GetFileStats(0, &used, &load); 216 EXPECT_EQ(101, used); 217 EXPECT_EQ(9, load); 218 219 files.GetFileStats(1, &used, &load); 220 EXPECT_EQ(203, used); 221 EXPECT_EQ(19, load); 222 223 files.GetFileStats(2, &used, &load); 224 EXPECT_EQ(0, used); 225 EXPECT_EQ(0, load); 226} 227 228} // namespace disk_cache 229