xref: /aosp_15_r20/external/cronet/net/disk_cache/simple/simple_version_upgrade_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
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 <stdint.h>
8 #include <string>
9 
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/format_macros.h"
14 #include "base/strings/stringprintf.h"
15 #include "net/base/net_errors.h"
16 #include "net/disk_cache/disk_cache.h"
17 #include "net/disk_cache/simple/simple_backend_version.h"
18 #include "net/disk_cache/simple/simple_entry_format_history.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 
21 namespace {
22 
23 // Same as |disk_cache::kSimpleInitialMagicNumber|.
24 const uint64_t kSimpleInitialMagicNumber = UINT64_C(0xfcfb6d1ba7725c30);
25 
26 // The "fake index" file that cache backends use to distinguish whether the
27 // cache belongs to one backend or another.
28 const char kFakeIndexFileName[] = "index";
29 
30 // Same as |SimpleIndexFile::kIndexDirectory|.
31 const char kIndexDirName[] = "index-dir";
32 
33 // Same as |SimpleIndexFile::kIndexFileName|.
34 const char kIndexFileName[] = "the-real-index";
35 
WriteFakeIndexFileV5(const base::FilePath & cache_path)36 bool WriteFakeIndexFileV5(const base::FilePath& cache_path) {
37   disk_cache::FakeIndexData data;
38   data.version = 5;
39   data.initial_magic_number = kSimpleInitialMagicNumber;
40   data.zero = 0;
41   data.zero2 = 0;
42   const base::FilePath file_name = cache_path.AppendASCII("index");
43   return base::WriteFile(file_name, base::as_bytes(base::make_span(&data, 1u)));
44 }
45 
TEST(SimpleVersionUpgradeTest,FailsToMigrateBackwards)46 TEST(SimpleVersionUpgradeTest, FailsToMigrateBackwards) {
47   base::ScopedTempDir cache_dir;
48   ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
49   const base::FilePath cache_path = cache_dir.GetPath();
50 
51   disk_cache::FakeIndexData data;
52   data.version = 100500;
53   data.initial_magic_number = kSimpleInitialMagicNumber;
54   data.zero = 0;
55   data.zero2 = 0;
56   const base::FilePath file_name = cache_path.AppendASCII(kFakeIndexFileName);
57   ASSERT_TRUE(
58       base::WriteFile(file_name, base::as_bytes(base::make_span(&data, 1u))));
59   disk_cache::TrivialFileOperations file_operations;
60   EXPECT_EQ(disk_cache::SimpleCacheConsistencyResult::kVersionFromTheFuture,
61             disk_cache::UpgradeSimpleCacheOnDisk(&file_operations,
62                                                  cache_dir.GetPath()));
63 }
64 
TEST(SimpleVersionUpgradeTest,ExperimentBacktoDefault)65 TEST(SimpleVersionUpgradeTest, ExperimentBacktoDefault) {
66   base::ScopedTempDir cache_dir;
67   ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
68   const base::FilePath cache_path = cache_dir.GetPath();
69 
70   disk_cache::FakeIndexData data;
71   data.version = disk_cache::kSimpleVersion;
72   data.initial_magic_number = kSimpleInitialMagicNumber;
73   data.zero = 2;
74   data.zero2 = 4;
75   const base::FilePath file_name = cache_path.AppendASCII(kFakeIndexFileName);
76   ASSERT_TRUE(
77       base::WriteFile(file_name, base::as_bytes(base::make_span(&data, 1u))));
78 
79   disk_cache::TrivialFileOperations file_operations;
80   // The cache needs to transition from a deprecated experiment back to not
81   // having one.
82   EXPECT_EQ(disk_cache::SimpleCacheConsistencyResult::kBadZeroCheck,
83             disk_cache::UpgradeSimpleCacheOnDisk(&file_operations,
84                                                  cache_dir.GetPath()));
85 }
86 
TEST(SimpleVersionUpgradeTest,FakeIndexVersionGetsUpdated)87 TEST(SimpleVersionUpgradeTest, FakeIndexVersionGetsUpdated) {
88   base::ScopedTempDir cache_dir;
89   ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
90   const base::FilePath cache_path = cache_dir.GetPath();
91 
92   WriteFakeIndexFileV5(cache_path);
93   const std::string file_contents("incorrectly serialized data");
94   const base::FilePath index_file = cache_path.AppendASCII(kIndexFileName);
95   ASSERT_TRUE(base::WriteFile(index_file, file_contents));
96 
97   disk_cache::TrivialFileOperations file_operations;
98   // Upgrade.
99   ASSERT_EQ(disk_cache::SimpleCacheConsistencyResult::kOK,
100             disk_cache::UpgradeSimpleCacheOnDisk(&file_operations, cache_path));
101 
102   // Check that the version in the fake index file is updated.
103   std::string new_fake_index_contents;
104   ASSERT_TRUE(base::ReadFileToString(cache_path.AppendASCII(kFakeIndexFileName),
105                                      &new_fake_index_contents));
106   const disk_cache::FakeIndexData* fake_index_header;
107   EXPECT_EQ(sizeof(*fake_index_header), new_fake_index_contents.size());
108   fake_index_header = reinterpret_cast<const disk_cache::FakeIndexData*>(
109       new_fake_index_contents.data());
110   EXPECT_EQ(disk_cache::kSimpleVersion, fake_index_header->version);
111   EXPECT_EQ(kSimpleInitialMagicNumber, fake_index_header->initial_magic_number);
112 }
113 
TEST(SimpleVersionUpgradeTest,UpgradeV5V6IndexMustDisappear)114 TEST(SimpleVersionUpgradeTest, UpgradeV5V6IndexMustDisappear) {
115   base::ScopedTempDir cache_dir;
116   ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
117   const base::FilePath cache_path = cache_dir.GetPath();
118 
119   WriteFakeIndexFileV5(cache_path);
120   const std::string file_contents("incorrectly serialized data");
121   const base::FilePath index_file = cache_path.AppendASCII(kIndexFileName);
122   ASSERT_TRUE(base::WriteFile(index_file, file_contents));
123 
124   // Create a few entry-like files.
125   const uint64_t kEntries = 5;
126   for (uint64_t entry_hash = 0; entry_hash < kEntries; ++entry_hash) {
127     for (int index = 0; index < 3; ++index) {
128       std::string file_name =
129           base::StringPrintf("%016" PRIx64 "_%1d", entry_hash, index);
130       std::string entry_contents =
131           file_contents +
132           base::StringPrintf(" %" PRIx64, static_cast<uint64_t>(entry_hash));
133       ASSERT_TRUE(
134           base::WriteFile(cache_path.AppendASCII(file_name), entry_contents));
135     }
136   }
137 
138   disk_cache::TrivialFileOperations file_operations;
139   // Upgrade.
140   ASSERT_TRUE(disk_cache::UpgradeIndexV5V6(&file_operations, cache_path));
141 
142   // Check that the old index disappeared but the files remain unchanged.
143   EXPECT_FALSE(base::PathExists(index_file));
144   for (uint64_t entry_hash = 0; entry_hash < kEntries; ++entry_hash) {
145     for (int index = 0; index < 3; ++index) {
146       std::string file_name =
147           base::StringPrintf("%016" PRIx64 "_%1d", entry_hash, index);
148       std::string expected_contents =
149           file_contents +
150           base::StringPrintf(" %" PRIx64, static_cast<uint64_t>(entry_hash));
151       std::string real_contents;
152       EXPECT_TRUE(base::ReadFileToString(cache_path.AppendASCII(file_name),
153                                          &real_contents));
154       EXPECT_EQ(expected_contents, real_contents);
155     }
156   }
157 }
158 
TEST(SimpleVersionUpgradeTest,DeleteAllIndexFilesWhenCacheIsEmpty)159 TEST(SimpleVersionUpgradeTest, DeleteAllIndexFilesWhenCacheIsEmpty) {
160   const std::string kCorruptData("corrupt");
161 
162   base::ScopedTempDir cache_dir;
163   ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
164   const base::FilePath cache_path = cache_dir.GetPath();
165 
166   const base::FilePath fake_index = cache_path.AppendASCII(kFakeIndexFileName);
167   ASSERT_TRUE(base::WriteFile(fake_index, kCorruptData));
168 
169   const base::FilePath index_path = cache_path.AppendASCII(kIndexDirName);
170   ASSERT_TRUE(base::CreateDirectory(index_path));
171 
172   const base::FilePath index = index_path.AppendASCII(kIndexFileName);
173   ASSERT_TRUE(base::WriteFile(index, kCorruptData));
174 
175   EXPECT_TRUE(disk_cache::DeleteIndexFilesIfCacheIsEmpty(cache_path));
176   EXPECT_TRUE(base::PathExists(cache_path));
177   EXPECT_TRUE(base::IsDirectoryEmpty(cache_path));
178 }
179 
TEST(SimpleVersionUpgradeTest,DoesNotDeleteIndexFilesWhenCacheIsNotEmpty)180 TEST(SimpleVersionUpgradeTest, DoesNotDeleteIndexFilesWhenCacheIsNotEmpty) {
181   const std::string kCorruptData("corrupt");
182 
183   base::ScopedTempDir cache_dir;
184   ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
185   const base::FilePath cache_path = cache_dir.GetPath();
186 
187   const base::FilePath fake_index = cache_path.AppendASCII(kFakeIndexFileName);
188   ASSERT_TRUE(base::WriteFile(fake_index, kCorruptData));
189 
190   const base::FilePath index_path = cache_path.AppendASCII(kIndexDirName);
191   ASSERT_TRUE(base::CreateDirectory(index_path));
192 
193   const base::FilePath index = index_path.AppendASCII(kIndexFileName);
194   ASSERT_TRUE(base::WriteFile(index, kCorruptData));
195 
196   const base::FilePath entry_file = cache_path.AppendASCII("01234567_0");
197   ASSERT_TRUE(base::WriteFile(entry_file, kCorruptData));
198 
199   EXPECT_FALSE(disk_cache::DeleteIndexFilesIfCacheIsEmpty(cache_path));
200   EXPECT_TRUE(base::PathExists(cache_path));
201   EXPECT_FALSE(base::IsDirectoryEmpty(cache_path));
202   EXPECT_TRUE(base::PathExists(fake_index));
203   EXPECT_TRUE(base::PathExists(index_path));
204   EXPECT_TRUE(base::PathExists(index));
205   EXPECT_TRUE(base::PathExists(entry_file));
206 }
207 
208 }  // namespace
209