blob: cbefa225a4754a2fd969fe5f98cdfc92b9ba1198 [file] [log] [blame]
[email protected]330278c2012-07-05 09:43:551// Copyright (c) 2012 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
yawano3513e142016-04-20 00:42:425#include "components/drive/chromeos/file_cache.h"
[email protected]21ed99072012-09-13 01:49:336
okac6aac502016-05-23 12:16:587#include <linux/fs.h>
avibc5337b2015-12-25 23:16:338#include <stddef.h>
9#include <stdint.h>
okac6aac502016-05-23 12:16:5810#include <sys/ioctl.h>
11#include <sys/xattr.h>
avibc5337b2015-12-25 23:16:3312
Stuart Langleybe4035742018-05-10 05:32:2713#include <memory>
[email protected]2333b2a12013-04-26 07:22:2214#include <string>
[email protected]79c3752d2012-07-17 12:10:0815#include <vector>
16
[email protected]8b03ab3a2014-01-15 17:52:4517#include "base/callback_helpers.h"
okac6aac502016-05-23 12:16:5818#include "base/files/file.h"
[email protected]25a4c1c2013-06-08 04:53:3619#include "base/files/file_enumerator.h"
thestig18dfb7a52014-08-26 10:44:0420#include "base/files/file_util.h"
[email protected]2333b2a12013-04-26 07:22:2221#include "base/files/scoped_temp_dir.h"
Daniel Chengd07ef712019-03-28 23:13:4122#include "base/hash/md5.h"
[email protected]b7af4f12013-10-31 06:57:4523#include "base/path_service.h"
Gabriel Charette078e3662017-08-28 22:59:0424#include "base/run_loop.h"
pranay.kumar229290b52015-05-14 05:21:0425#include "base/single_thread_task_runner.h"
okac6aac502016-05-23 12:16:5826#include "base/stl_util.h"
yawano4c36b9a02015-10-23 06:17:2327#include "base/strings/stringprintf.h"
gab7966d312016-05-11 20:35:0128#include "base/threading/thread_task_runner_handle.h"
yawano4c36b9a02015-10-23 06:17:2329#include "base/time/time.h"
yawano3513e142016-04-20 00:42:4230#include "components/drive/chromeos/drive_test_util.h"
31#include "components/drive/chromeos/fake_free_disk_space_getter.h"
lukasza01b9d55a2015-07-21 15:19:2532#include "components/drive/drive.pb.h"
lukasza6364a022015-08-21 01:13:2433#include "components/drive/file_system_core_util.h"
34#include "components/drive/resource_metadata_storage.h"
Gabriel Charettec7108742019-08-23 03:31:4035#include "content/public/test/browser_task_environment.h"
[email protected]e196bef32013-12-03 05:33:1336#include "google_apis/drive/test_util.h"
[email protected]330278c2012-07-05 09:43:5537#include "testing/gtest/include/gtest/gtest.h"
38
[email protected]d9d04df2012-10-12 07:06:3539namespace drive {
[email protected]59c7cdec2013-05-07 04:17:1340namespace internal {
[email protected]330278c2012-07-05 09:43:5541namespace {
42
okac6aac502016-05-23 12:16:5843typedef long FileAttributes; // NOLINT(runtime/int)
44
yawano9fd1e632016-02-04 09:00:0645const base::FilePath::CharType kCacheFileDirectory[] =
46 FILE_PATH_LITERAL("files");
yawano9fd1e632016-02-04 09:00:0647
yawano4c36b9a02015-10-23 06:17:2348const int kTemporaryFileSizeInBytes = 10;
[email protected]3e8d64d2013-09-19 10:09:0549
okac6aac502016-05-23 12:16:5850FileAttributes GetFileAttributes(const base::FilePath& file_path) {
51 base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
52 if (!file.IsValid()) {
53 ADD_FAILURE() << "Failed to open file: " << file_path.value();
yawano1c325bf2016-04-20 06:37:0354 return -1;
55 }
okac6aac502016-05-23 12:16:5856 FileAttributes flags = 0;
57 if (ioctl(file.GetPlatformFile(), FS_IOC_GETFLAGS, &flags) < 0) {
58 ADD_FAILURE() << "Failed to get attributes: " << file_path.value();
59 return -1;
60 }
61 return flags;
62}
63
64bool HasRemovableFlag(const base::FilePath& file_path) {
65 return (GetFileAttributes(file_path) & FS_NODUMP_FL) == FS_NODUMP_FL;
yawano1c325bf2016-04-20 06:37:0366}
67
Sergei Datsenkoe5a99eb2018-08-31 06:30:3968bool HasRemovableAttribute(const base::FilePath& file_path) {
69 return getxattr(file_path.value().c_str(),
70 FileCache::kGCacheRemovableAttribute, nullptr, 0) >= 0;
71}
72
73bool IsMarkedAsRemovable(const base::FilePath& path) {
74 return HasRemovableFlag(path) && HasRemovableAttribute(path);
75}
76
[email protected]4743aa1c2012-07-13 14:54:2377} // namespace
[email protected]330278c2012-07-05 09:43:5578
[email protected]f8b1a532013-06-06 08:35:0879// Tests FileCache methods working with the blocking task runner.
80class FileCacheTest : public testing::Test {
81 protected:
dchengfe773302015-01-22 19:45:5282 void SetUp() override {
[email protected]f8b1a532013-06-06 08:35:0883 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
vabr96fd0c0f2016-09-13 14:21:3184 const base::FilePath metadata_dir = temp_dir_.GetPath().AppendASCII("meta");
85 cache_files_dir_ = temp_dir_.GetPath().Append(kCacheFileDirectory);
[email protected]04727b62013-09-09 10:02:1586
[email protected]426d1c92013-12-03 20:08:5487 ASSERT_TRUE(base::CreateDirectory(metadata_dir));
88 ASSERT_TRUE(base::CreateDirectory(cache_files_dir_));
[email protected]e07f7b7b2013-06-19 03:43:1289
Stuart Langleybe4035742018-05-10 05:32:2790 fake_free_disk_space_getter_ = std::make_unique<FakeFreeDiskSpaceGetter>();
[email protected]f8b1a532013-06-06 08:35:0891
[email protected]2df61e12013-06-21 16:00:0992 metadata_storage_.reset(new ResourceMetadataStorage(
[email protected]04727b62013-09-09 10:02:1593 metadata_dir,
pranay.kumar229290b52015-05-14 05:21:0494 base::ThreadTaskRunnerHandle::Get().get()));
[email protected]2df61e12013-06-21 16:00:0995 ASSERT_TRUE(metadata_storage_->Initialize());
96
yawano4c36b9a02015-10-23 06:17:2397 cache_.reset(new FileCache(metadata_storage_.get(), cache_files_dir_,
98 base::ThreadTaskRunnerHandle::Get().get(),
99 fake_free_disk_space_getter_.get()));
[email protected]34a1bbf32013-06-17 07:24:02100 ASSERT_TRUE(cache_->Initialize());
[email protected]f8b1a532013-06-06 08:35:08101 }
102
[email protected]f2731d12013-10-22 03:23:15103 static bool RenameCacheFilesToNewFormat(FileCache* cache) {
104 return cache->RenameCacheFilesToNewFormat();
[email protected]91a464e62013-07-10 09:30:06105 }
106
okac6aac502016-05-23 12:16:58107 base::FilePath GetCacheFilePath(const std::string& id) {
108 return cache_->GetCacheFilePath(id);
109 }
110
yawano4c36b9a02015-10-23 06:17:23111 base::FilePath AddTestEntry(const std::string id,
112 const std::string md5,
113 const time_t last_accessed,
114 const base::FilePath& src_file) {
115 ResourceEntry entry;
116 entry.set_local_id(id);
117 entry.mutable_file_info()->set_last_accessed(last_accessed);
118 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
119 EXPECT_EQ(FILE_ERROR_OK,
120 cache_->Store(id, md5, src_file, FileCache::FILE_OPERATION_COPY));
121
122 base::FilePath path;
123 EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(id, &path));
124
125 // Update last modified and accessed time.
126 base::Time time = base::Time::FromTimeT(last_accessed);
127 EXPECT_TRUE(base::TouchFile(path, time, time));
128
129 return path;
130 }
131
Gabriel Charette798fde72019-08-20 22:24:04132 content::BrowserTaskEnvironment task_environment_;
[email protected]f8b1a532013-06-06 08:35:08133 base::ScopedTempDir temp_dir_;
[email protected]823ca9712013-09-13 10:09:09134 base::FilePath cache_files_dir_;
[email protected]f8b1a532013-06-06 08:35:08135
dchengf42750232016-04-12 04:12:27136 std::unique_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
[email protected]2df61e12013-06-21 16:00:09137 metadata_storage_;
dchengf42750232016-04-12 04:12:27138 std::unique_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
139 std::unique_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
[email protected]f8b1a532013-06-06 08:35:08140};
141
[email protected]b7af4f12013-10-31 06:57:45142TEST_F(FileCacheTest, RecoverFilesFromCacheDirectory) {
143 base::FilePath dir_source_root;
Avi Drissmanf617d012018-05-02 18:48:53144 EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &dir_source_root));
[email protected]b7af4f12013-10-31 06:57:45145 const base::FilePath src_path =
146 dir_source_root.AppendASCII("chrome/test/data/chromeos/drive/image.png");
147
148 // Store files. This file should not be moved.
[email protected]cd8fd37f2014-05-20 15:45:21149 ResourceEntry entry;
150 entry.set_local_id("id_foo");
151 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]b7af4f12013-10-31 06:57:45152 EXPECT_EQ(FILE_ERROR_OK, cache_->Store("id_foo", "md5", src_path,
153 FileCache::FILE_OPERATION_COPY));
154
155 // Set up files in the cache directory. These files should be moved.
[email protected]3e8d64d2013-09-19 10:09:05156 const base::FilePath file_directory =
vabr96fd0c0f2016-09-13 14:21:31157 temp_dir_.GetPath().Append(kCacheFileDirectory);
[email protected]b7af4f12013-10-31 06:57:45158 ASSERT_TRUE(base::CopyFile(src_path, file_directory.AppendASCII("id_bar")));
159 ASSERT_TRUE(base::CopyFile(src_path, file_directory.AppendASCII("id_baz")));
[email protected]e8842b192013-06-11 04:05:14160
[email protected]026d4a522013-11-05 14:22:18161 // Insert a dirty entry with "id_baz" to |recovered_cache_info|.
[email protected]760abc32013-11-01 05:13:01162 // This should not prevent the file from being recovered.
[email protected]026d4a522013-11-05 14:22:18163 ResourceMetadataStorage::RecoveredCacheInfoMap recovered_cache_info;
164 recovered_cache_info["id_baz"].is_dirty = true;
165 recovered_cache_info["id_baz"].title = "baz.png";
[email protected]760abc32013-11-01 05:13:01166
[email protected]b7af4f12013-10-31 06:57:45167 // Recover files.
vabr96fd0c0f2016-09-13 14:21:31168 const base::FilePath dest_directory = temp_dir_.GetPath().AppendASCII("dest");
[email protected]760abc32013-11-01 05:13:01169 EXPECT_TRUE(cache_->RecoverFilesFromCacheDirectory(dest_directory,
[email protected]026d4a522013-11-05 14:22:18170 recovered_cache_info));
[email protected]2df61e12013-06-21 16:00:09171
[email protected]b7af4f12013-10-31 06:57:45172 // Only two files should be recovered.
173 EXPECT_TRUE(base::PathExists(dest_directory));
[email protected]026d4a522013-11-05 14:22:18174 // base::FileEnumerator does not guarantee the order.
175 if (base::PathExists(dest_directory.AppendASCII("baz00000001.png"))) {
176 EXPECT_TRUE(base::ContentsEqual(
177 src_path,
178 dest_directory.AppendASCII("baz00000001.png")));
179 EXPECT_TRUE(base::ContentsEqual(
180 src_path,
181 dest_directory.AppendASCII("image00000002.png")));
182 } else {
183 EXPECT_TRUE(base::ContentsEqual(
184 src_path,
185 dest_directory.AppendASCII("image00000001.png")));
186 EXPECT_TRUE(base::ContentsEqual(
187 src_path,
188 dest_directory.AppendASCII("baz00000002.png")));
189 }
190 EXPECT_FALSE(base::PathExists(
191 dest_directory.AppendASCII("image00000003.png")));
[email protected]e8842b192013-06-11 04:05:14192}
193
[email protected]f8b1a532013-06-06 08:35:08194TEST_F(FileCacheTest, FreeDiskSpaceIfNeededFor) {
195 base::FilePath src_file;
vabr96fd0c0f2016-09-13 14:21:31196 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &src_file));
[email protected]f8b1a532013-06-06 08:35:08197
198 // Store a file as a 'temporary' file and remember the path.
[email protected]c9e4738d2013-08-26 03:04:07199 const std::string id_tmp = "id_tmp", md5_tmp = "md5_tmp";
yawano4c36b9a02015-10-23 06:17:23200 const time_t last_accessed_tmp = 1;
201 const base::FilePath& tmp_path =
202 AddTestEntry(id_tmp, md5_tmp, last_accessed_tmp, src_file);
[email protected]f8b1a532013-06-06 08:35:08203
204 // Store a file as a pinned file and remember the path.
[email protected]c9e4738d2013-08-26 03:04:07205 const std::string id_pinned = "id_pinned", md5_pinned = "md5_pinned";
yawano4c36b9a02015-10-23 06:17:23206 const time_t last_accessed_pinned = 1;
207 const base::FilePath& pinned_path =
208 AddTestEntry(id_pinned, md5_pinned, last_accessed_pinned, src_file);
[email protected]c9e4738d2013-08-26 03:04:07209 ASSERT_EQ(FILE_ERROR_OK, cache_->Pin(id_pinned));
[email protected]f8b1a532013-06-06 08:35:08210
211 // Call FreeDiskSpaceIfNeededFor().
212 fake_free_disk_space_getter_->set_default_value(test_util::kLotsOfSpace);
213 fake_free_disk_space_getter_->PushFakeValue(0);
yawano4c36b9a02015-10-23 06:17:23214 fake_free_disk_space_getter_->PushFakeValue(0);
avibc5337b2015-12-25 23:16:33215 const int64_t kNeededBytes = 1;
[email protected]f8b1a532013-06-06 08:35:08216 EXPECT_TRUE(cache_->FreeDiskSpaceIfNeededFor(kNeededBytes));
217
218 // Only 'temporary' file gets removed.
yawano4c36b9a02015-10-23 06:17:23219 ResourceEntry entry;
[email protected]cd8fd37f2014-05-20 15:45:21220 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_tmp, &entry));
221 EXPECT_FALSE(entry.file_specific_info().cache_state().is_present());
[email protected]7567484142013-07-11 17:36:07222 EXPECT_FALSE(base::PathExists(tmp_path));
[email protected]f8b1a532013-06-06 08:35:08223
[email protected]cd8fd37f2014-05-20 15:45:21224 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_pinned, &entry));
225 EXPECT_TRUE(entry.file_specific_info().cache_state().is_present());
[email protected]7567484142013-07-11 17:36:07226 EXPECT_TRUE(base::PathExists(pinned_path));
[email protected]f8b1a532013-06-06 08:35:08227
228 // Returns false when disk space cannot be freed.
229 fake_free_disk_space_getter_->set_default_value(0);
230 EXPECT_FALSE(cache_->FreeDiskSpaceIfNeededFor(kNeededBytes));
231}
232
yawano4c36b9a02015-10-23 06:17:23233TEST_F(FileCacheTest, EvictDriveCacheInLRU) {
234 // Create temporary file.
235 base::FilePath src_file;
vabr96fd0c0f2016-09-13 14:21:31236 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &src_file));
yawano4c36b9a02015-10-23 06:17:23237 ASSERT_EQ(kTemporaryFileSizeInBytes,
238 base::WriteFile(src_file, "abcdefghij", kTemporaryFileSizeInBytes));
239
240 // Add entries.
241 const std::string id_a = "id_a", md5_a = "md5_a";
242 const time_t last_accessed_a = 1;
243 const base::FilePath& a_path =
244 AddTestEntry(id_a, md5_a, last_accessed_a, src_file);
245
246 const std::string id_pinned = "id_pinned", md5_pinned = "md5_pinned";
247 const time_t last_accessed_pinned = 2;
248 const base::FilePath& pinned_path =
249 AddTestEntry(id_pinned, md5_pinned, last_accessed_pinned, src_file);
250 ASSERT_EQ(FILE_ERROR_OK, cache_->Pin(id_pinned));
251
252 const std::string id_b = "id_b", md5_b = "md5_b";
253 const time_t last_accessed_b = 3;
254 const base::FilePath& b_path =
255 AddTestEntry(id_b, md5_b, last_accessed_b, src_file);
256
257 const std::string id_c = "id_c", md5_c = "md5_c";
258 const time_t last_accessed_c = 4;
259 const base::FilePath& c_path =
260 AddTestEntry(id_c, md5_c, last_accessed_c, src_file);
261
262 // Call FreeDiskSpaceIfNeededFor.
263 fake_free_disk_space_getter_->set_default_value(test_util::kLotsOfSpace);
264 fake_free_disk_space_getter_->PushFakeValue(kMinFreeSpaceInBytes);
265 fake_free_disk_space_getter_->PushFakeValue(kMinFreeSpaceInBytes);
avibc5337b2015-12-25 23:16:33266 const int64_t kNeededBytes = kTemporaryFileSizeInBytes * 3 / 2;
yawano4c36b9a02015-10-23 06:17:23267 EXPECT_TRUE(cache_->FreeDiskSpaceIfNeededFor(kNeededBytes));
268
269 // Entry A is evicted.
270 ResourceEntry entry;
271 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_a, &entry));
272 EXPECT_FALSE(entry.file_specific_info().cache_state().is_present());
273 EXPECT_FALSE(base::PathExists(a_path));
274
275 // Pinned entry should not be evicted.
276 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_pinned, &entry));
277 EXPECT_TRUE(entry.file_specific_info().cache_state().is_present());
278 EXPECT_TRUE(base::PathExists(pinned_path));
279
280 // Entry B is evicted.
281 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_b, &entry));
282 EXPECT_FALSE(entry.file_specific_info().cache_state().is_present());
283 EXPECT_FALSE(base::PathExists(b_path));
284
285 // Entry C should not be evicted.
286 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_c, &entry));
287 EXPECT_TRUE(entry.file_specific_info().cache_state().is_present());
288 EXPECT_TRUE(base::PathExists(c_path));
289}
290
291// Test case for deleting invalid cache files which don't have corresponding
292// metadata.
293TEST_F(FileCacheTest, EvictInvalidCacheFile) {
294 base::FilePath src_file;
vabr96fd0c0f2016-09-13 14:21:31295 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &src_file));
yawano4c36b9a02015-10-23 06:17:23296
297 // Add entries.
298 const std::string id_a = "id_a", md5_a = "md5_a";
299 const time_t last_accessed_a = 1;
300 const base::FilePath& a_path =
301 AddTestEntry(id_a, md5_a, last_accessed_a, src_file);
302
303 const std::string id_b = "id_b", md5_b = "md5_b";
304 const time_t last_accessed_b = 2;
305 const base::FilePath& b_path =
306 AddTestEntry(id_b, md5_b, last_accessed_b, src_file);
307
308 // Remove metadata of entry B.
309 ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->RemoveEntry(id_b));
310
311 // Confirm cache file of entry B exists.
312 ASSERT_TRUE(base::PathExists(b_path));
313
314 // Run FreeDiskSpaceIfNeededFor.
315 fake_free_disk_space_getter_->set_default_value(test_util::kLotsOfSpace);
316 fake_free_disk_space_getter_->PushFakeValue(kMinFreeSpaceInBytes);
avibc5337b2015-12-25 23:16:33317 const int64_t kNeededBytes = 1;
yawano4c36b9a02015-10-23 06:17:23318 EXPECT_TRUE(cache_->FreeDiskSpaceIfNeededFor(kNeededBytes));
319
320 // Entry A is not evicted.
321 ResourceEntry entry;
322 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_a, &entry));
323 EXPECT_TRUE(entry.file_specific_info().cache_state().is_present());
324 EXPECT_TRUE(base::PathExists(a_path));
325
326 // Entry B is evicted.
327 EXPECT_EQ(FILE_ERROR_NOT_FOUND, metadata_storage_->GetEntry(id_b, &entry));
328 EXPECT_FALSE(base::PathExists(b_path));
329}
330
331TEST_F(FileCacheTest, TooManyCacheFiles) {
332 const size_t kMaxNumOfEvictedCacheFiles = 50;
333 cache_->SetMaxNumOfEvictedCacheFilesForTest(kMaxNumOfEvictedCacheFiles);
334
335 // Create temporary file.
336 base::FilePath src_file;
vabr96fd0c0f2016-09-13 14:21:31337 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &src_file));
yawano4c36b9a02015-10-23 06:17:23338 ASSERT_EQ(kTemporaryFileSizeInBytes,
339 base::WriteFile(src_file, "abcdefghij", kTemporaryFileSizeInBytes));
340
341 // Add kNumOfTestFiles=kMaxNumOfEvictedCacheFiles*2 entries.
342 std::vector<base::FilePath> paths;
avibc5337b2015-12-25 23:16:33343 const int32_t kNumOfTestFiles = kMaxNumOfEvictedCacheFiles * 2;
yawano4c36b9a02015-10-23 06:17:23344 for (int i = 0; i < kNumOfTestFiles; ++i) {
345 // Set last accessed in reverse order to the file name. i.e. If you sort
346 // files in name-asc order, they will be last access desc order.
347 paths.push_back(AddTestEntry(
348 base::StringPrintf("id_%02d", i), base::StringPrintf("md5_%02d", i),
349 kNumOfTestFiles - i /* last accessed */, src_file));
350 }
351
352 // Confirm cache files of kNumOfTestFiles actually exist.
353 for (const auto& path : paths) {
354 ASSERT_TRUE(base::PathExists(path)) << path.value();
355 }
356
357 // Try to free kMaxNumOfEvictedCacheFiles * 3 / 2.
358 fake_free_disk_space_getter_->set_default_value(test_util::kLotsOfSpace);
359 fake_free_disk_space_getter_->PushFakeValue(kMinFreeSpaceInBytes);
360 fake_free_disk_space_getter_->PushFakeValue(kMinFreeSpaceInBytes);
361 fake_free_disk_space_getter_->PushFakeValue(
362 kMinFreeSpaceInBytes +
363 (kMaxNumOfEvictedCacheFiles * kTemporaryFileSizeInBytes));
avibc5337b2015-12-25 23:16:33364 const int64_t kNeededBytes =
yawano4c36b9a02015-10-23 06:17:23365 (kMaxNumOfEvictedCacheFiles * 3 / 2) * kTemporaryFileSizeInBytes;
366 EXPECT_FALSE(cache_->FreeDiskSpaceIfNeededFor(kNeededBytes));
367
avibc5337b2015-12-25 23:16:33368 for (uint32_t i = 0; i < kNumOfTestFiles; ++i) {
yawano4c36b9a02015-10-23 06:17:23369 // Assert that only first kMaxNumOfEvictedCacheFiles exist.
370 ASSERT_EQ(i < kMaxNumOfEvictedCacheFiles, base::PathExists(paths[i]));
371 }
372}
373
[email protected]9cbea7032013-09-24 07:54:53374TEST_F(FileCacheTest, GetFile) {
vabr96fd0c0f2016-09-13 14:21:31375 const base::FilePath src_file_path = temp_dir_.GetPath().Append("test.dat");
[email protected]9cbea7032013-09-24 07:54:53376 const std::string src_contents = "test";
377 EXPECT_TRUE(google_apis::test_util::WriteStringToFile(src_file_path,
378 src_contents));
379 std::string id("id1");
380 std::string md5(base::MD5String(src_contents));
381
382 const base::FilePath cache_file_directory =
vabr96fd0c0f2016-09-13 14:21:31383 temp_dir_.GetPath().Append(kCacheFileDirectory);
[email protected]9cbea7032013-09-24 07:54:53384
385 // Try to get an existing file from cache.
[email protected]cd8fd37f2014-05-20 15:45:21386 ResourceEntry entry;
387 entry.set_local_id(id);
388 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]9cbea7032013-09-24 07:54:53389 EXPECT_EQ(FILE_ERROR_OK, cache_->Store(id, md5, src_file_path,
390 FileCache::FILE_OPERATION_COPY));
391 base::FilePath cache_file_path;
392 EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(id, &cache_file_path));
393 EXPECT_EQ(
394 cache_file_directory.AppendASCII(util::EscapeCacheFileName(id)).value(),
395 cache_file_path.value());
396
397 std::string contents;
398 EXPECT_TRUE(base::ReadFileToString(cache_file_path, &contents));
399 EXPECT_EQ(src_contents, contents);
400
401 // Get file from cache with different id.
402 id = "id2";
[email protected]cd8fd37f2014-05-20 15:45:21403 entry.Clear();
404 entry.set_local_id(id);
405 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]9cbea7032013-09-24 07:54:53406 EXPECT_EQ(FILE_ERROR_NOT_FOUND, cache_->GetFile(id, &cache_file_path));
407
408 // Pin a non-existent file.
409 EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(id));
410
411 // Get the non-existent pinned file from cache.
412 EXPECT_EQ(FILE_ERROR_NOT_FOUND, cache_->GetFile(id, &cache_file_path));
413
414 // Get a previously pinned and stored file from cache.
415 EXPECT_EQ(FILE_ERROR_OK, cache_->Store(id, md5, src_file_path,
416 FileCache::FILE_OPERATION_COPY));
417
418 EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(id, &cache_file_path));
419 EXPECT_EQ(
420 cache_file_directory.AppendASCII(util::EscapeCacheFileName(id)).value(),
421 cache_file_path.value());
422
423 contents.clear();
424 EXPECT_TRUE(base::ReadFileToString(cache_file_path, &contents));
425 EXPECT_EQ(src_contents, contents);
426}
427
[email protected]834673b2014-02-20 18:34:43428TEST_F(FileCacheTest, Store) {
vabr96fd0c0f2016-09-13 14:21:31429 const base::FilePath src_file_path = temp_dir_.GetPath().Append("test.dat");
[email protected]834673b2014-02-20 18:34:43430 const std::string src_contents = "test";
431 EXPECT_TRUE(google_apis::test_util::WriteStringToFile(src_file_path,
432 src_contents));
433 std::string id("id");
434 std::string md5(base::MD5String(src_contents));
435
436 // Store a file.
[email protected]cd8fd37f2014-05-20 15:45:21437 ResourceEntry entry;
438 entry.set_local_id(id);
439 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]834673b2014-02-20 18:34:43440 EXPECT_EQ(FILE_ERROR_OK, cache_->Store(
441 id, md5, src_file_path, FileCache::FILE_OPERATION_COPY));
442
[email protected]cd8fd37f2014-05-20 15:45:21443 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
444 EXPECT_TRUE(entry.file_specific_info().cache_state().is_present());
445 EXPECT_EQ(md5, entry.file_specific_info().cache_state().md5());
[email protected]834673b2014-02-20 18:34:43446
447 base::FilePath cache_file_path;
448 EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(id, &cache_file_path));
449 EXPECT_TRUE(base::ContentsEqual(src_file_path, cache_file_path));
450
okac6aac502016-05-23 12:16:58451 base::FilePath dest_file_path = GetCacheFilePath(id);
Sergei Datsenkoe5a99eb2018-08-31 06:30:39452 EXPECT_TRUE(IsMarkedAsRemovable(dest_file_path));
okac6aac502016-05-23 12:16:58453
[email protected]834673b2014-02-20 18:34:43454 // Store a non-existent file.
455 EXPECT_EQ(FILE_ERROR_FAILED, cache_->Store(
456 id, md5, base::FilePath::FromUTF8Unsafe("non_existent_file"),
457 FileCache::FILE_OPERATION_COPY));
458
459 // Passing empty MD5 marks the entry as dirty.
460 EXPECT_EQ(FILE_ERROR_OK, cache_->Store(
461 id, std::string(), src_file_path, FileCache::FILE_OPERATION_COPY));
462
[email protected]cd8fd37f2014-05-20 15:45:21463 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
464 EXPECT_TRUE(entry.file_specific_info().cache_state().is_present());
465 EXPECT_TRUE(entry.file_specific_info().cache_state().md5().empty());
466 EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
Sergei Datsenkoe5a99eb2018-08-31 06:30:39467 EXPECT_FALSE(IsMarkedAsRemovable(dest_file_path));
[email protected]834673b2014-02-20 18:34:43468
469 // No free space available.
470 fake_free_disk_space_getter_->set_default_value(0);
471
472 EXPECT_EQ(FILE_ERROR_NO_LOCAL_SPACE, cache_->Store(
473 id, md5, src_file_path, FileCache::FILE_OPERATION_COPY));
474}
475
476TEST_F(FileCacheTest, PinAndUnpin) {
vabr96fd0c0f2016-09-13 14:21:31477 const base::FilePath src_file_path = temp_dir_.GetPath().Append("test.dat");
[email protected]834673b2014-02-20 18:34:43478 const std::string src_contents = "test";
479 EXPECT_TRUE(google_apis::test_util::WriteStringToFile(src_file_path,
480 src_contents));
481 std::string id("id_present");
482 std::string md5(base::MD5String(src_contents));
483
484 // Store a file.
[email protected]cd8fd37f2014-05-20 15:45:21485 ResourceEntry entry;
486 entry.set_local_id(id);
487 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]834673b2014-02-20 18:34:43488 EXPECT_EQ(FILE_ERROR_OK, cache_->Store(
489 id, md5, src_file_path, FileCache::FILE_OPERATION_COPY));
490
okac6aac502016-05-23 12:16:58491 const base::FilePath dest_file_path = GetCacheFilePath(id);
[email protected]cd8fd37f2014-05-20 15:45:21492 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
493 EXPECT_FALSE(entry.file_specific_info().cache_state().is_pinned());
Sergei Datsenkoe5a99eb2018-08-31 06:30:39494 EXPECT_TRUE(IsMarkedAsRemovable(dest_file_path));
[email protected]834673b2014-02-20 18:34:43495
496 // Pin the existing file.
497 EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(id));
498
[email protected]cd8fd37f2014-05-20 15:45:21499 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
500 EXPECT_TRUE(entry.file_specific_info().cache_state().is_pinned());
Sergei Datsenkoe5a99eb2018-08-31 06:30:39501 EXPECT_FALSE(IsMarkedAsRemovable(dest_file_path));
[email protected]834673b2014-02-20 18:34:43502
503 // Unpin the file.
504 EXPECT_EQ(FILE_ERROR_OK, cache_->Unpin(id));
505
[email protected]cd8fd37f2014-05-20 15:45:21506 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
507 EXPECT_FALSE(entry.file_specific_info().cache_state().is_pinned());
Sergei Datsenkoe5a99eb2018-08-31 06:30:39508 EXPECT_TRUE(IsMarkedAsRemovable(dest_file_path));
[email protected]834673b2014-02-20 18:34:43509
510 // Pin a non-present file.
511 std::string id_non_present = "id_non_present";
[email protected]cd8fd37f2014-05-20 15:45:21512 entry.Clear();
513 entry.set_local_id(id_non_present);
514 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]834673b2014-02-20 18:34:43515 EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(id_non_present));
516
[email protected]cd8fd37f2014-05-20 15:45:21517 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_non_present, &entry));
518 EXPECT_TRUE(entry.file_specific_info().cache_state().is_pinned());
[email protected]834673b2014-02-20 18:34:43519
520 // Unpin the previously pinned non-existent file.
521 EXPECT_EQ(FILE_ERROR_OK, cache_->Unpin(id_non_present));
522
[email protected]cd8fd37f2014-05-20 15:45:21523 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_non_present, &entry));
524 EXPECT_FALSE(entry.file_specific_info().has_cache_state());
[email protected]834673b2014-02-20 18:34:43525
526 // Unpin a file that doesn't exist in cache and is not pinned.
527 EXPECT_EQ(FILE_ERROR_NOT_FOUND, cache_->Unpin("id_non_existent"));
528}
529
530TEST_F(FileCacheTest, MountUnmount) {
vabr96fd0c0f2016-09-13 14:21:31531 const base::FilePath src_file_path = temp_dir_.GetPath().Append("test.dat");
[email protected]834673b2014-02-20 18:34:43532 const std::string src_contents = "test";
533 EXPECT_TRUE(google_apis::test_util::WriteStringToFile(src_file_path,
534 src_contents));
535 std::string id("id_present");
536 std::string md5(base::MD5String(src_contents));
537
538 // Store a file.
[email protected]cd8fd37f2014-05-20 15:45:21539 ResourceEntry entry;
540 entry.set_local_id(id);
541 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]834673b2014-02-20 18:34:43542 EXPECT_EQ(FILE_ERROR_OK, cache_->Store(
543 id, md5, src_file_path, FileCache::FILE_OPERATION_COPY));
544
545 // Mark the file mounted.
546 base::FilePath cache_file_path;
547 EXPECT_EQ(FILE_ERROR_OK, cache_->MarkAsMounted(id, &cache_file_path));
548
Tatsuhisa Yamaguchi48101282018-03-20 02:18:39549 EXPECT_TRUE(cache_->IsMarkedAsMounted(id));
550
[email protected]834673b2014-02-20 18:34:43551 // Try to remove it.
552 EXPECT_EQ(FILE_ERROR_IN_USE, cache_->Remove(id));
553
554 // Clear mounted state of the file.
555 EXPECT_EQ(FILE_ERROR_OK, cache_->MarkAsUnmounted(cache_file_path));
556
Tatsuhisa Yamaguchi48101282018-03-20 02:18:39557 EXPECT_FALSE(cache_->IsMarkedAsMounted(id));
558
[email protected]834673b2014-02-20 18:34:43559 // Try to remove again.
560 EXPECT_EQ(FILE_ERROR_OK, cache_->Remove(id));
561}
562
[email protected]8b03ab3a2014-01-15 17:52:45563TEST_F(FileCacheTest, OpenForWrite) {
564 // Prepare a file.
565 base::FilePath src_file;
vabr96fd0c0f2016-09-13 14:21:31566 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &src_file));
[email protected]8b03ab3a2014-01-15 17:52:45567
568 const std::string id = "id";
[email protected]cd8fd37f2014-05-20 15:45:21569 ResourceEntry entry;
570 entry.set_local_id(id);
571 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]8b03ab3a2014-01-15 17:52:45572 ASSERT_EQ(FILE_ERROR_OK, cache_->Store(id, "md5", src_file,
573 FileCache::FILE_OPERATION_COPY));
[email protected]f92367ae2014-06-02 07:35:43574 EXPECT_EQ(0, entry.file_info().last_modified());
Shuhei Takahashia25ace562017-09-15 09:22:17575 EXPECT_EQ(0, entry.last_modified_by_me());
[email protected]8b03ab3a2014-01-15 17:52:45576
[email protected]b1bf19a2014-01-21 04:45:19577 // Entry is not dirty nor opened.
[email protected]8b03ab3a2014-01-15 17:52:45578 EXPECT_FALSE(cache_->IsOpenedForWrite(id));
[email protected]cd8fd37f2014-05-20 15:45:21579 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
580 EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
[email protected]8b03ab3a2014-01-15 17:52:45581
okac6aac502016-05-23 12:16:58582 const base::FilePath dest_file = GetCacheFilePath(id);
Sergei Datsenkoe5a99eb2018-08-31 06:30:39583 EXPECT_TRUE(IsMarkedAsRemovable(dest_file));
okac6aac502016-05-23 12:16:58584
[email protected]8b03ab3a2014-01-15 17:52:45585 // Open (1).
dchengf42750232016-04-12 04:12:27586 std::unique_ptr<base::ScopedClosureRunner> file_closer1;
[email protected]8b03ab3a2014-01-15 17:52:45587 EXPECT_EQ(FILE_ERROR_OK, cache_->OpenForWrite(id, &file_closer1));
588 EXPECT_TRUE(cache_->IsOpenedForWrite(id));
589
[email protected]b1bf19a2014-01-21 04:45:19590 // Entry is dirty.
[email protected]cd8fd37f2014-05-20 15:45:21591 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
592 EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
Sergei Datsenkoe5a99eb2018-08-31 06:30:39593 EXPECT_FALSE(IsMarkedAsRemovable((dest_file)));
[email protected]b1bf19a2014-01-21 04:45:19594
[email protected]8b03ab3a2014-01-15 17:52:45595 // Open (2).
dchengf42750232016-04-12 04:12:27596 std::unique_ptr<base::ScopedClosureRunner> file_closer2;
[email protected]8b03ab3a2014-01-15 17:52:45597 EXPECT_EQ(FILE_ERROR_OK, cache_->OpenForWrite(id, &file_closer2));
598 EXPECT_TRUE(cache_->IsOpenedForWrite(id));
599
600 // Close (1).
601 file_closer1.reset();
[email protected]c929c932014-07-23 06:06:05602 base::RunLoop().RunUntilIdle();
[email protected]8b03ab3a2014-01-15 17:52:45603 EXPECT_TRUE(cache_->IsOpenedForWrite(id));
604
Shuhei Takahashia25ace562017-09-15 09:22:17605 // last_modified and last_modified_by_me are updated.
[email protected]f92367ae2014-06-02 07:35:43606 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
607 EXPECT_NE(0, entry.file_info().last_modified());
Shuhei Takahashia25ace562017-09-15 09:22:17608 EXPECT_NE(0, entry.last_modified_by_me());
609 EXPECT_EQ(entry.file_info().last_modified(), entry.last_modified_by_me());
[email protected]f92367ae2014-06-02 07:35:43610
[email protected]8b03ab3a2014-01-15 17:52:45611 // Close (2).
612 file_closer2.reset();
[email protected]c929c932014-07-23 06:06:05613 base::RunLoop().RunUntilIdle();
[email protected]8b03ab3a2014-01-15 17:52:45614 EXPECT_FALSE(cache_->IsOpenedForWrite(id));
615
616 // Try to open non-existent file.
617 EXPECT_EQ(FILE_ERROR_NOT_FOUND,
618 cache_->OpenForWrite("nonexistent_id", &file_closer1));
619}
620
[email protected]b1bf19a2014-01-21 04:45:19621TEST_F(FileCacheTest, UpdateMd5) {
622 // Store test data.
vabr96fd0c0f2016-09-13 14:21:31623 const base::FilePath src_file_path = temp_dir_.GetPath().Append("test.dat");
[email protected]b1bf19a2014-01-21 04:45:19624 const std::string contents_before = "before";
625 EXPECT_TRUE(google_apis::test_util::WriteStringToFile(src_file_path,
626 contents_before));
627 std::string id("id1");
[email protected]cd8fd37f2014-05-20 15:45:21628 ResourceEntry entry;
629 entry.set_local_id(id);
630 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]b1bf19a2014-01-21 04:45:19631 EXPECT_EQ(FILE_ERROR_OK, cache_->Store(id, base::MD5String(contents_before),
632 src_file_path,
633 FileCache::FILE_OPERATION_COPY));
634
635 // Modify the cache file.
dchengf42750232016-04-12 04:12:27636 std::unique_ptr<base::ScopedClosureRunner> file_closer;
[email protected]b1bf19a2014-01-21 04:45:19637 EXPECT_EQ(FILE_ERROR_OK, cache_->OpenForWrite(id, &file_closer));
638 base::FilePath cache_file_path;
639 EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(id, &cache_file_path));
640 const std::string contents_after = "after";
641 EXPECT_TRUE(google_apis::test_util::WriteStringToFile(cache_file_path,
642 contents_after));
643
644 // Cannot update MD5 of an opend file.
645 EXPECT_EQ(FILE_ERROR_IN_USE, cache_->UpdateMd5(id));
646
647 // Close file.
648 file_closer.reset();
[email protected]c929c932014-07-23 06:06:05649 base::RunLoop().RunUntilIdle();
[email protected]b1bf19a2014-01-21 04:45:19650
651 // MD5 was cleared by OpenForWrite().
[email protected]cd8fd37f2014-05-20 15:45:21652 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
653 EXPECT_TRUE(entry.file_specific_info().cache_state().md5().empty());
[email protected]b1bf19a2014-01-21 04:45:19654
655 // Update MD5.
656 EXPECT_EQ(FILE_ERROR_OK, cache_->UpdateMd5(id));
[email protected]cd8fd37f2014-05-20 15:45:21657 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
658 EXPECT_EQ(base::MD5String(contents_after),
659 entry.file_specific_info().cache_state().md5());
[email protected]b1bf19a2014-01-21 04:45:19660}
661
662TEST_F(FileCacheTest, ClearDirty) {
663 // Prepare a file.
664 base::FilePath src_file;
vabr96fd0c0f2016-09-13 14:21:31665 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &src_file));
[email protected]b1bf19a2014-01-21 04:45:19666
667 const std::string id = "id";
[email protected]cd8fd37f2014-05-20 15:45:21668 ResourceEntry entry;
669 entry.set_local_id(id);
670 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]b1bf19a2014-01-21 04:45:19671 ASSERT_EQ(FILE_ERROR_OK, cache_->Store(id, "md5", src_file,
672 FileCache::FILE_OPERATION_COPY));
673
okac6aac502016-05-23 12:16:58674 const base::FilePath dest_file = GetCacheFilePath(id);
Sergei Datsenkoe5a99eb2018-08-31 06:30:39675 EXPECT_TRUE(IsMarkedAsRemovable(dest_file));
okac6aac502016-05-23 12:16:58676
[email protected]b1bf19a2014-01-21 04:45:19677 // Open the file.
dchengf42750232016-04-12 04:12:27678 std::unique_ptr<base::ScopedClosureRunner> file_closer;
[email protected]b1bf19a2014-01-21 04:45:19679 EXPECT_EQ(FILE_ERROR_OK, cache_->OpenForWrite(id, &file_closer));
680
681 // Entry is dirty.
[email protected]cd8fd37f2014-05-20 15:45:21682 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
683 EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
Sergei Datsenkoe5a99eb2018-08-31 06:30:39684 EXPECT_FALSE(IsMarkedAsRemovable(dest_file));
[email protected]b1bf19a2014-01-21 04:45:19685
686 // Cannot clear the dirty bit of an opened entry.
687 EXPECT_EQ(FILE_ERROR_IN_USE, cache_->ClearDirty(id));
Sergei Datsenkoe5a99eb2018-08-31 06:30:39688 EXPECT_FALSE(IsMarkedAsRemovable(dest_file));
[email protected]b1bf19a2014-01-21 04:45:19689
690 // Close the file and clear the dirty bit.
691 file_closer.reset();
[email protected]c929c932014-07-23 06:06:05692 base::RunLoop().RunUntilIdle();
[email protected]b1bf19a2014-01-21 04:45:19693 EXPECT_EQ(FILE_ERROR_OK, cache_->ClearDirty(id));
694
695 // Entry is not dirty.
[email protected]cd8fd37f2014-05-20 15:45:21696 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
697 EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
Sergei Datsenkoe5a99eb2018-08-31 06:30:39698 EXPECT_TRUE(IsMarkedAsRemovable(dest_file));
[email protected]b1bf19a2014-01-21 04:45:19699}
700
[email protected]834673b2014-02-20 18:34:43701TEST_F(FileCacheTest, Remove) {
vabr96fd0c0f2016-09-13 14:21:31702 const base::FilePath src_file_path = temp_dir_.GetPath().Append("test.dat");
[email protected]834673b2014-02-20 18:34:43703 const std::string src_contents = "test";
704 EXPECT_TRUE(google_apis::test_util::WriteStringToFile(src_file_path,
705 src_contents));
706 std::string id("id");
707 std::string md5(base::MD5String(src_contents));
708
709 // First store a file to cache.
[email protected]cd8fd37f2014-05-20 15:45:21710 ResourceEntry entry;
711 entry.set_local_id(id);
712 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]834673b2014-02-20 18:34:43713 base::FilePath src_file;
vabr96fd0c0f2016-09-13 14:21:31714 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &src_file));
[email protected]834673b2014-02-20 18:34:43715 EXPECT_EQ(FILE_ERROR_OK, cache_->Store(
716 id, md5, src_file_path, FileCache::FILE_OPERATION_COPY));
717
718 base::FilePath cache_file_path;
719 EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(id, &cache_file_path));
720
721 // Then try to remove existing file from cache.
722 EXPECT_EQ(FILE_ERROR_OK, cache_->Remove(id));
723 EXPECT_FALSE(base::PathExists(cache_file_path));
724}
725
[email protected]91a464e62013-07-10 09:30:06726TEST_F(FileCacheTest, RenameCacheFilesToNewFormat) {
[email protected]3e8d64d2013-09-19 10:09:05727 const base::FilePath file_directory =
vabr96fd0c0f2016-09-13 14:21:31728 temp_dir_.GetPath().Append(kCacheFileDirectory);
[email protected]91a464e62013-07-10 09:30:06729
[email protected]f2731d12013-10-22 03:23:15730 // File with an old style "<prefix>:<ID>.<MD5>" name.
[email protected]91a464e62013-07-10 09:30:06731 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(
[email protected]f2731d12013-10-22 03:23:15732 file_directory.AppendASCII("file:id_koo.md5"), "koo"));
[email protected]91a464e62013-07-10 09:30:06733
734 // File with multiple extensions should be removed.
735 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(
736 file_directory.AppendASCII("id_kyu.md5.mounted"), "kyu (mounted)"));
737 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(
738 file_directory.AppendASCII("id_kyu.md5"), "kyu"));
739
740 // Rename and verify the result.
[email protected]f2731d12013-10-22 03:23:15741 EXPECT_TRUE(RenameCacheFilesToNewFormat(cache_.get()));
[email protected]91a464e62013-07-10 09:30:06742 std::string contents;
[email protected]82f84b92013-08-30 18:23:50743 EXPECT_TRUE(base::ReadFileToString(file_directory.AppendASCII("id_koo"),
[email protected]f2731d12013-10-22 03:23:15744 &contents));
[email protected]91a464e62013-07-10 09:30:06745 EXPECT_EQ("koo", contents);
746 contents.clear();
[email protected]82f84b92013-08-30 18:23:50747 EXPECT_TRUE(base::ReadFileToString(file_directory.AppendASCII("id_kyu"),
[email protected]f2731d12013-10-22 03:23:15748 &contents));
[email protected]91a464e62013-07-10 09:30:06749 EXPECT_EQ("kyu", contents);
750
751 // Rename again.
[email protected]f2731d12013-10-22 03:23:15752 EXPECT_TRUE(RenameCacheFilesToNewFormat(cache_.get()));
[email protected]91a464e62013-07-10 09:30:06753
754 // Files with new style names are not affected.
755 contents.clear();
[email protected]82f84b92013-08-30 18:23:50756 EXPECT_TRUE(base::ReadFileToString(file_directory.AppendASCII("id_koo"),
[email protected]f2731d12013-10-22 03:23:15757 &contents));
[email protected]91a464e62013-07-10 09:30:06758 EXPECT_EQ("koo", contents);
759 contents.clear();
[email protected]82f84b92013-08-30 18:23:50760 EXPECT_TRUE(base::ReadFileToString(file_directory.AppendASCII("id_kyu"),
[email protected]f2731d12013-10-22 03:23:15761 &contents));
[email protected]91a464e62013-07-10 09:30:06762 EXPECT_EQ("kyu", contents);
763}
764
okac6aac502016-05-23 12:16:58765TEST_F(FileCacheTest, FixMetadataAndFileAttributes) {
yawano9fd1e632016-02-04 09:00:06766 // Create test files and metadata.
767 base::FilePath temp_file;
vabr96fd0c0f2016-09-13 14:21:31768 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file));
yawano9fd1e632016-02-04 09:00:06769
okac6aac502016-05-23 12:16:58770 // Entry A: pinned cache file.
yawano9fd1e632016-02-04 09:00:06771 const std::string id_a = "id_a";
772 ResourceEntry entry_a;
773 entry_a.set_local_id(id_a);
okac6aac502016-05-23 12:16:58774 FileCacheEntry* file_cache_entry_a =
775 entry_a.mutable_file_specific_info()->mutable_cache_state();
776 file_cache_entry_a->set_is_present(true);
777 file_cache_entry_a->set_is_pinned(true);
778 file_cache_entry_a->set_is_dirty(false);
yawano9fd1e632016-02-04 09:00:06779 ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_a));
okac6aac502016-05-23 12:16:58780 const base::FilePath file_path_a = GetCacheFilePath(id_a);
781 ASSERT_TRUE(base::CopyFile(temp_file, file_path_a));
yawano9fd1e632016-02-04 09:00:06782
okac6aac502016-05-23 12:16:58783 // Entry B: dirty cache file.
yawano9fd1e632016-02-04 09:00:06784 const std::string id_b = "id_b";
okac6aac502016-05-23 12:16:58785 ResourceEntry entry_b;
786 entry_b.set_local_id(id_b);
787 FileCacheEntry* file_cache_entry_b =
788 entry_b.mutable_file_specific_info()->mutable_cache_state();
789 file_cache_entry_b->set_is_present(true);
790 file_cache_entry_b->set_is_pinned(false);
791 file_cache_entry_b->set_is_dirty(true);
792 ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_b));
793 const base::FilePath file_path_b = GetCacheFilePath(id_b);
794 ASSERT_TRUE(base::CopyFile(temp_file, file_path_b));
yawano9fd1e632016-02-04 09:00:06795
okac6aac502016-05-23 12:16:58796 // Entry C: not pinned nor dirty cache file.
yawano9fd1e632016-02-04 09:00:06797 const std::string id_c = "id_c";
798 ResourceEntry entry_c;
799 entry_c.set_local_id(id_c);
okac6aac502016-05-23 12:16:58800 FileCacheEntry* file_cache_entry_c =
801 entry_c.mutable_file_specific_info()->mutable_cache_state();
802 file_cache_entry_c->set_is_present(true);
803 file_cache_entry_c->set_is_pinned(false);
804 file_cache_entry_c->set_is_dirty(false);
yawano9fd1e632016-02-04 09:00:06805 ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_c));
okac6aac502016-05-23 12:16:58806 const base::FilePath file_path_c = GetCacheFilePath(id_c);
807 ASSERT_TRUE(base::CopyFile(temp_file, file_path_c));
yawano9fd1e632016-02-04 09:00:06808
okac6aac502016-05-23 12:16:58809 // Entry D: pinned cache file somehow having removable flag.
yawano9fd1e632016-02-04 09:00:06810 const std::string id_d = "id_d";
811 ResourceEntry entry_d;
812 entry_d.set_local_id(id_d);
okac6aac502016-05-23 12:16:58813 FileCacheEntry* file_cache_entry_d =
814 entry_d.mutable_file_specific_info()->mutable_cache_state();
815 file_cache_entry_d->set_is_present(true);
816 file_cache_entry_d->set_is_pinned(true);
817 file_cache_entry_d->set_is_dirty(false);
yawano9fd1e632016-02-04 09:00:06818 ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_d));
okac6aac502016-05-23 12:16:58819 const base::FilePath file_path_d = GetCacheFilePath(id_d);
820 ASSERT_TRUE(base::CopyFile(temp_file, file_path_d));
yawano9fd1e632016-02-04 09:00:06821
okac6aac502016-05-23 12:16:58822 // Set removable flag.
823 FileAttributes flags = GetFileAttributes(file_path_d);
824 ASSERT_GE(flags, 0);
825 flags |= FS_NODUMP_FL;
826 base::File file_d(file_path_d, base::File::FLAG_OPEN | base::File::FLAG_READ);
827 ASSERT_EQ(ioctl(file_d.GetPlatformFile(), FS_IOC_SETFLAGS, &flags), 0);
828
829 // Entry E: there is no file; removed by cryptohome.
yawano1c325bf2016-04-20 06:37:03830 const std::string id_e = "id_e";
831 ResourceEntry entry_e;
832 entry_e.set_local_id(id_e);
833 FileCacheEntry* file_cache_entry_e =
834 entry_e.mutable_file_specific_info()->mutable_cache_state();
835 file_cache_entry_e->set_is_present(true);
okac6aac502016-05-23 12:16:58836 file_cache_entry_e->set_is_pinned(false);
yawano1c325bf2016-04-20 06:37:03837 file_cache_entry_e->set_is_dirty(false);
838 ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_e));
okac6aac502016-05-23 12:16:58839 const base::FilePath file_path_e = GetCacheFilePath(id_e);
yawano1c325bf2016-04-20 06:37:03840
okac6aac502016-05-23 12:16:58841 // Entry F: there is a file, but metadata says not.
yawano1c325bf2016-04-20 06:37:03842 const std::string id_f = "id_f";
843 ResourceEntry entry_f;
844 entry_f.set_local_id(id_f);
okac6aac502016-05-23 12:16:58845 entry_f.mutable_file_specific_info()->mutable_cache_state()->set_is_present(
846 false);
yawano1c325bf2016-04-20 06:37:03847 ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_f));
okac6aac502016-05-23 12:16:58848 const base::FilePath file_path_f = GetCacheFilePath(id_f);
849 ASSERT_TRUE(base::CopyFile(temp_file, file_path_f));
yawano1c325bf2016-04-20 06:37:03850
okac6aac502016-05-23 12:16:58851 // Entry G: no file nor metadata.
yawano1c325bf2016-04-20 06:37:03852 const std::string id_g = "id_g";
853 ResourceEntry entry_g;
854 entry_g.set_local_id(id_g);
okac6aac502016-05-23 12:16:58855 entry_f.mutable_file_specific_info()->mutable_cache_state()->set_is_present(
856 false);
857 ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_f));
yawano1c325bf2016-04-20 06:37:03858
okac6aac502016-05-23 12:16:58859 // Initialize fixes inconsistency between metadata and cache file attributes
860 // as well as adding specific file attributes to the cache directory.
861 ASSERT_TRUE(cache_->Initialize());
yawano9fd1e632016-02-04 09:00:06862
863 // Check result.
Sergei Datsenkoe5a99eb2018-08-31 06:30:39864 EXPECT_FALSE(IsMarkedAsRemovable(file_path_a));
865 EXPECT_FALSE(IsMarkedAsRemovable(file_path_b));
866 EXPECT_TRUE(IsMarkedAsRemovable(file_path_c));
867 EXPECT_FALSE(IsMarkedAsRemovable(file_path_d));
okac6aac502016-05-23 12:16:58868 EXPECT_FALSE(base::PathExists(file_path_f));
869
870 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_e, &entry_e));
871 EXPECT_FALSE(entry_e.file_specific_info().cache_state().is_present());
872 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_f, &entry_f));
873 EXPECT_FALSE(entry_f.file_specific_info().cache_state().is_present());
874
875 // Check the cache dir has appropriate attributes.
Sergei Datsenkoe5a99eb2018-08-31 06:30:39876 EXPECT_TRUE(HasRemovableFlag(cache_files_dir_));
okac6aac502016-05-23 12:16:58877 EXPECT_GE(getxattr(cache_files_dir_.value().c_str(),
878 FileCache::kGCacheFilesAttribute, nullptr, 0), 0);
yawano9fd1e632016-02-04 09:00:06879}
880
[email protected]823ca9712013-09-13 10:09:09881TEST_F(FileCacheTest, ClearAll) {
[email protected]a70a91e2014-08-04 11:49:20882 const std::string id("1a2b");
[email protected]823ca9712013-09-13 10:09:09883 const std::string md5("abcdef0123456789");
884
885 // Store an existing file.
[email protected]cd8fd37f2014-05-20 15:45:21886 ResourceEntry entry;
887 entry.set_local_id(id);
888 EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry));
[email protected]823ca9712013-09-13 10:09:09889 base::FilePath src_file;
vabr96fd0c0f2016-09-13 14:21:31890 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &src_file));
[email protected]823ca9712013-09-13 10:09:09891 ASSERT_EQ(FILE_ERROR_OK,
892 cache_->Store(id, md5, src_file, FileCache::FILE_OPERATION_COPY));
893
[email protected]823ca9712013-09-13 10:09:09894 // Clear cache.
895 EXPECT_TRUE(cache_->ClearAll());
896
897 // Verify that the cache is removed.
[email protected]fb4bcfa32013-12-02 18:55:49898 EXPECT_TRUE(base::IsDirectoryEmpty(cache_files_dir_));
[email protected]823ca9712013-09-13 10:09:09899}
900
[email protected]59c7cdec2013-05-07 04:17:13901} // namespace internal
902} // namespace drive