1d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_util.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/block_files.h"
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/disk_cache.h"
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/disk_cache_test_base.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/disk_cache_test_util.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Time;
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns the number of files in this folder.
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint NumberOfFiles(const FilePath& path) {
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file_util::FileEnumerator iter(path, false, file_util::FileEnumerator::FILES);
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int count = 0;
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (FilePath file = iter.Next(); !file.value().empty(); file = iter.Next()) {
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    count++;
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return count;
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace;
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache {
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DiskCacheTest, BlockFiles_Grow) {
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path = GetCacheFilePath();
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(DeleteCache(path));
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(file_util::CreateDirectory(path));
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  BlockFiles files(path);
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(files.Init(true));
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int kMaxSize = 35000;
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address[kMaxSize];
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Fill up the 32-byte block file (use three files).
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kMaxSize; i++) {
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(files.CreateBlock(RANKINGS, 4, &address[i]));
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(6, NumberOfFiles(path));
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Make sure we don't keep adding files.
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kMaxSize * 4; i += 2) {
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int target = i % kMaxSize;
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    files.DeleteBlock(address[target], false);
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(files.CreateBlock(RANKINGS, 4, &address[target]));
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(6, NumberOfFiles(path));
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We should be able to delete empty block files.
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DiskCacheTest, BlockFiles_Shrink) {
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path = GetCacheFilePath();
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(DeleteCache(path));
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(file_util::CreateDirectory(path));
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  BlockFiles files(path);
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(files.Init(true));
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int kMaxSize = 35000;
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address[kMaxSize];
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Fill up the 32-byte block file (use three files).
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kMaxSize; i++) {
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(files.CreateBlock(RANKINGS, 4, &address[i]));
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Now delete all the blocks, so that we can delete the two extra files.
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kMaxSize; i++) {
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    files.DeleteBlock(address[i], false);
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(4, NumberOfFiles(path));
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Handling of block files not properly closed.
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DiskCacheTest, BlockFiles_Recover) {
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path = GetCacheFilePath();
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(DeleteCache(path));
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(file_util::CreateDirectory(path));
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  BlockFiles files(path);
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(files.Init(true));
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int kNumEntries = 2000;
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheAddr entries[kNumEntries];
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int seed = static_cast<int>(Time::Now().ToInternalValue());
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  srand(seed);
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kNumEntries; i++) {
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Addr address(0);
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int size = (rand() % 4) + 1;
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(files.CreateBlock(RANKINGS, size, &address));
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entries[i] = address.value();
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kNumEntries; i++) {
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int source1 = rand() % kNumEntries;
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int source2 = rand() % kNumEntries;
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CacheAddr temp = entries[source1];
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entries[source1] = entries[source2];
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entries[source2] = temp;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kNumEntries / 2; i++) {
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Addr address(entries[i]);
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    files.DeleteBlock(address, false);
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // At this point, there are kNumEntries / 2 entries on the file, randomly
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // distributed both on location and size.
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entries[kNumEntries / 2]);
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MappedFile* file = files.GetFile(address);
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(NULL != file);
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  BlockFileHeader* header =
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<BlockFileHeader*>(file->buffer());
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(NULL != header);
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_EQ(0, header->updating);
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int max_entries = header->max_entries;
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int empty_1 = header->empty[0];
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int empty_2 = header->empty[1];
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int empty_3 = header->empty[2];
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int empty_4 = header->empty[3];
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Corrupt the file.
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  header->max_entries = header->empty[0] = 0;
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  header->empty[1] = header->empty[2] = header->empty[3] = 0;
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  header->updating = -1;
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  files.CloseFiles();
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(files.Init(false));
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The file must have been fixed.
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file = files.GetFile(address);
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(NULL != file);
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  header = reinterpret_cast<BlockFileHeader*>(file->buffer());
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(NULL != header);
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_EQ(0, header->updating);
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(max_entries, header->max_entries);
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(empty_1, header->empty[0]);
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(empty_2, header->empty[1]);
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(empty_3, header->empty[2]);
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(empty_4, header->empty[3]);
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Handling of truncated files.
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DiskCacheTest, BlockFiles_ZeroSizeFile) {
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path = GetCacheFilePath();
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(DeleteCache(path));
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(file_util::CreateDirectory(path));
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  BlockFiles files(path);
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(files.Init(true));
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath filename = files.Name(0);
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  files.CloseFiles();
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Truncate one of the files.
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  {
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    scoped_refptr<File> file(new File);
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ASSERT_TRUE(file->Init(filename));
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(file->SetLength(0));
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Initializing should fail, not crash.
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_FALSE(files.Init(false));
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
180d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen// Handling of truncated files (non empty).
181d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian MonsenTEST_F(DiskCacheTest, BlockFiles_TruncatedFile) {
182d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  FilePath path = GetCacheFilePath();
183d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  ASSERT_TRUE(DeleteCache(path));
184d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  ASSERT_TRUE(file_util::CreateDirectory(path));
185d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen
186d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  BlockFiles files(path);
187d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  ASSERT_TRUE(files.Init(true));
188d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  Addr address;
189d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  EXPECT_TRUE(files.CreateBlock(RANKINGS, 2, &address));
190d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen
191d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  FilePath filename = files.Name(0);
192d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  files.CloseFiles();
193d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  // Truncate one of the files.
194d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  {
195d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen    scoped_refptr<File> file(new File);
196d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen    ASSERT_TRUE(file->Init(filename));
197d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen    EXPECT_TRUE(file->SetLength(15000));
198d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  }
199d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen
200d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  // Initializing should fail, not crash.
201d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen  ASSERT_FALSE(files.Init(false));
202d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen}
203d129b9e5870dc7fa49745121bf987e1b6ead1b51Kristian Monsen
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// An invalid file can be detected after init.
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(DiskCacheTest, BlockFiles_InvalidFile) {
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path = GetCacheFilePath();
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(DeleteCache(path));
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(file_util::CreateDirectory(path));
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  BlockFiles files(path);
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(files.Init(true));
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Let's access block 10 of file 5. (There is no file).
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr addr(BLOCK_256, 1, 5, 10);
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(NULL == files.GetFile(addr));
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Let's create an invalid file.
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath filename(files.Name(5));
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char header[kBlockHeaderSize];
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(header, 'a', kBlockHeaderSize);
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(kBlockHeaderSize,
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            file_util::WriteFile(filename, header, kBlockHeaderSize));
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(NULL == files.GetFile(addr));
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The file should not have been cached (it is still invalid).
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(NULL == files.GetFile(addr));
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests that we generate the correct file stats.
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(DiskCacheTest, BlockFiles_Stats) {
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(CopyTestCache("remove_load1"));
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath path = GetCacheFilePath();
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BlockFiles files(path);
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(files.Init(false));
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int used, load;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  files.GetFileStats(0, &used, &load);
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(101, used);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(9, load);
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  files.GetFileStats(1, &used, &load);
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(203, used);
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(19, load);
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  files.GetFileStats(2, &used, &load);
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(0, used);
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(0, load);
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Tests that we add and remove blocks correctly.
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_F(DiskCacheTest, AllocationMap) {
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath path = GetCacheFilePath();
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(DeleteCache(path));
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(file_util::CreateDirectory(path));
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BlockFiles files(path);
2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(files.Init(true));
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Create a bunch of entries.
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kSize = 100;
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Addr address[kSize];
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < kSize; i++) {
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SCOPED_TRACE(i);
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int block_size = i % 4 + 1;
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_TRUE(files.CreateBlock(BLOCK_1K, block_size, &address[i]));
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(BLOCK_1K, address[i].file_type());
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(block_size, address[i].num_blocks());
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int start = address[i].start_block();
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(start / 4, (start + block_size - 1) / 4);
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < kSize; i++) {
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SCOPED_TRACE(i);
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_TRUE(files.IsValid(address[i]));
2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // The first part of the allocation map should be completely filled. We used
2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // 10 bits per each four entries, so 250 bits total.
2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BlockFileHeader* header =
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      reinterpret_cast<BlockFileHeader*>(files.GetFile(address[0])->buffer());
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  uint8* buffer = reinterpret_cast<uint8*>(&header->allocation_map);
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i =0; i < 29; i++) {
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SCOPED_TRACE(i);
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0xff, buffer[i]);
2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < kSize; i++) {
2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SCOPED_TRACE(i);
2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    files.DeleteBlock(address[i], false);
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // The allocation map should be empty.
2953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i =0; i < 50; i++) {
2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SCOPED_TRACE(i);
2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0, buffer[i]);
2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace disk_cache
302