Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(505)

Unified Diff: components/drive/chromeos/file_cache_unittest.cc

Issue 2006503002: Reland of Mark removable Drive caches for cryptohome. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/drive/chromeos/file_cache.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/drive/chromeos/file_cache_unittest.cc
diff --git a/components/drive/chromeos/file_cache_unittest.cc b/components/drive/chromeos/file_cache_unittest.cc
index fce4211e117944097f2fc5a507362b2a0e21ae9e..b95512cb51925511ccadb50fb6a6788b5bc6bc24 100644
--- a/components/drive/chromeos/file_cache_unittest.cc
+++ b/components/drive/chromeos/file_cache_unittest.cc
@@ -4,22 +4,24 @@
#include "components/drive/chromeos/file_cache.h"
+#include <linux/fs.h>
#include <stddef.h>
#include <stdint.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/xattr.h>
#include <string>
#include <vector>
#include "base/callback_helpers.h"
+#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/md5.h"
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -36,20 +38,29 @@
namespace internal {
namespace {
+typedef long FileAttributes; // NOLINT(runtime/int)
+
const base::FilePath::CharType kCacheFileDirectory[] =
FILE_PATH_LITERAL("files");
-const base::FilePath::CharType kNewCacheFileDirectory[] =
- FILE_PATH_LITERAL("blobs");
-const base::FilePath::CharType kLinkDirectory[] = FILE_PATH_LITERAL("links");
const int kTemporaryFileSizeInBytes = 10;
-int GetNumberOfLinks(const base::FilePath& file_path) {
- struct stat result;
- if (stat(file_path.AsUTF8Unsafe().c_str(), &result) != 0) {
+FileAttributes GetFileAttributes(const base::FilePath& file_path) {
+ base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+ if (!file.IsValid()) {
+ ADD_FAILURE() << "Failed to open file: " << file_path.value();
return -1;
}
- return result.st_nlink;
+ FileAttributes flags = 0;
+ if (ioctl(file.GetPlatformFile(), FS_IOC_GETFLAGS, &flags) < 0) {
+ ADD_FAILURE() << "Failed to get attributes: " << file_path.value();
+ return -1;
+ }
+ return flags;
+}
+
+bool HasRemovableFlag(const base::FilePath& file_path) {
+ return (GetFileAttributes(file_path) & FS_NODUMP_FL) == FS_NODUMP_FL;
}
} // namespace
@@ -80,6 +91,10 @@
static bool RenameCacheFilesToNewFormat(FileCache* cache) {
return cache->RenameCacheFilesToNewFormat();
+ }
+
+ base::FilePath GetCacheFilePath(const std::string& id) {
+ return cache_->GetCacheFilePath(id);
}
base::FilePath AddTestEntry(const std::string id,
@@ -422,6 +437,9 @@
EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(id, &cache_file_path));
EXPECT_TRUE(base::ContentsEqual(src_file_path, cache_file_path));
+ base::FilePath dest_file_path = GetCacheFilePath(id);
+ EXPECT_TRUE(HasRemovableFlag((dest_file_path)));
+
// Store a non-existent file.
EXPECT_EQ(FILE_ERROR_FAILED, cache_->Store(
id, md5, base::FilePath::FromUTF8Unsafe("non_existent_file"),
@@ -435,6 +453,7 @@
EXPECT_TRUE(entry.file_specific_info().cache_state().is_present());
EXPECT_TRUE(entry.file_specific_info().cache_state().md5().empty());
EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
+ EXPECT_FALSE(HasRemovableFlag((dest_file_path)));
// No free space available.
fake_free_disk_space_getter_->set_default_value(0);
@@ -458,20 +477,24 @@
EXPECT_EQ(FILE_ERROR_OK, cache_->Store(
id, md5, src_file_path, FileCache::FILE_OPERATION_COPY));
+ const base::FilePath dest_file_path = GetCacheFilePath(id);
EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
EXPECT_FALSE(entry.file_specific_info().cache_state().is_pinned());
+ EXPECT_TRUE(HasRemovableFlag((dest_file_path)));
// Pin the existing file.
EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(id));
EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
EXPECT_TRUE(entry.file_specific_info().cache_state().is_pinned());
+ EXPECT_FALSE(HasRemovableFlag((dest_file_path)));
// Unpin the file.
EXPECT_EQ(FILE_ERROR_OK, cache_->Unpin(id));
EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
EXPECT_FALSE(entry.file_specific_info().cache_state().is_pinned());
+ EXPECT_TRUE(HasRemovableFlag((dest_file_path)));
// Pin a non-present file.
std::string id_non_present = "id_non_present";
@@ -540,6 +563,9 @@
EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
+ const base::FilePath dest_file = GetCacheFilePath(id);
+ EXPECT_TRUE(HasRemovableFlag((dest_file)));
+
// Open (1).
std::unique_ptr<base::ScopedClosureRunner> file_closer1;
EXPECT_EQ(FILE_ERROR_OK, cache_->OpenForWrite(id, &file_closer1));
@@ -548,6 +574,7 @@
// Entry is dirty.
EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
+ EXPECT_FALSE(HasRemovableFlag((dest_file)));
// Open (2).
std::unique_ptr<base::ScopedClosureRunner> file_closer2;
@@ -626,6 +653,9 @@
ASSERT_EQ(FILE_ERROR_OK, cache_->Store(id, "md5", src_file,
FileCache::FILE_OPERATION_COPY));
+ const base::FilePath dest_file = GetCacheFilePath(id);
+ EXPECT_TRUE(HasRemovableFlag((dest_file)));
+
// Open the file.
std::unique_ptr<base::ScopedClosureRunner> file_closer;
EXPECT_EQ(FILE_ERROR_OK, cache_->OpenForWrite(id, &file_closer));
@@ -633,9 +663,11 @@
// Entry is dirty.
EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
+ EXPECT_FALSE(HasRemovableFlag((dest_file)));
// Cannot clear the dirty bit of an opened entry.
EXPECT_EQ(FILE_ERROR_IN_USE, cache_->ClearDirty(id));
+ EXPECT_FALSE(HasRemovableFlag((dest_file)));
// Close the file and clear the dirty bit.
file_closer.reset();
@@ -645,6 +677,7 @@
// Entry is not dirty.
EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id, &entry));
EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
+ EXPECT_TRUE(HasRemovableFlag((dest_file)));
}
TEST_F(FileCacheTest, Remove) {
@@ -711,156 +744,120 @@
EXPECT_EQ("kyu", contents);
}
-// Test for migrating cache files from files to blobs.
-TEST_F(FileCacheTest, MigrateCacheFiles) {
+TEST_F(FileCacheTest, FixMetadataAndFileAttributes) {
// Create test files and metadata.
base::FilePath temp_file;
ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file));
- const base::FilePath old_cache_dir =
- temp_dir_.path().Append(kCacheFileDirectory);
- const base::FilePath new_cache_dir =
- temp_dir_.path().Append(kNewCacheFileDirectory);
- const base::FilePath link_dir = temp_dir_.path().Append(kLinkDirectory);
- ASSERT_TRUE(base::CreateDirectory(old_cache_dir));
- ASSERT_TRUE(base::CreateDirectory(new_cache_dir));
- ASSERT_TRUE(base::CreateDirectory(link_dir));
-
- // Entry A: cache file in old cache directory with metadata.
+ // Entry A: pinned cache file.
const std::string id_a = "id_a";
ResourceEntry entry_a;
entry_a.set_local_id(id_a);
- entry_a.mutable_file_specific_info()->mutable_cache_state()->set_is_present(
- true);
+ FileCacheEntry* file_cache_entry_a =
+ entry_a.mutable_file_specific_info()->mutable_cache_state();
+ file_cache_entry_a->set_is_present(true);
+ file_cache_entry_a->set_is_pinned(true);
+ file_cache_entry_a->set_is_dirty(false);
ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_a));
- const base::FilePath old_file_path_a = old_cache_dir.AppendASCII(id_a);
- const base::FilePath new_file_path_a = new_cache_dir.AppendASCII(id_a);
- ASSERT_TRUE(base::CopyFile(temp_file, old_file_path_a));
-
- // Entry B: cache file in old cache directory without metadata.
+ const base::FilePath file_path_a = GetCacheFilePath(id_a);
+ ASSERT_TRUE(base::CopyFile(temp_file, file_path_a));
+
+ // Entry B: dirty cache file.
const std::string id_b = "id_b";
- const base::FilePath old_file_path_b = old_cache_dir.AppendASCII(id_b);
- ASSERT_TRUE(base::CopyFile(temp_file, old_file_path_b));
-
- // Entry C: already migrated cache file.
+ ResourceEntry entry_b;
+ entry_b.set_local_id(id_b);
+ FileCacheEntry* file_cache_entry_b =
+ entry_b.mutable_file_specific_info()->mutable_cache_state();
+ file_cache_entry_b->set_is_present(true);
+ file_cache_entry_b->set_is_pinned(false);
+ file_cache_entry_b->set_is_dirty(true);
+ ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_b));
+ const base::FilePath file_path_b = GetCacheFilePath(id_b);
+ ASSERT_TRUE(base::CopyFile(temp_file, file_path_b));
+
+ // Entry C: not pinned nor dirty cache file.
const std::string id_c = "id_c";
ResourceEntry entry_c;
entry_c.set_local_id(id_c);
- entry_c.mutable_file_specific_info()->mutable_cache_state()->set_is_present(
- true);
+ FileCacheEntry* file_cache_entry_c =
+ entry_c.mutable_file_specific_info()->mutable_cache_state();
+ file_cache_entry_c->set_is_present(true);
+ file_cache_entry_c->set_is_pinned(false);
+ file_cache_entry_c->set_is_dirty(false);
ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_c));
- const base::FilePath new_file_path_c = new_cache_dir.AppendASCII(id_c);
- ASSERT_TRUE(base::CopyFile(temp_file, new_file_path_c));
-
- // Entry D: metadata entry without cache file.
+ const base::FilePath file_path_c = GetCacheFilePath(id_c);
+ ASSERT_TRUE(base::CopyFile(temp_file, file_path_c));
+
+ // Entry D: pinned cache file somehow having removable flag.
const std::string id_d = "id_d";
ResourceEntry entry_d;
entry_d.set_local_id(id_d);
- entry_d.mutable_file_specific_info()->mutable_cache_state()->set_is_present(
- true);
+ FileCacheEntry* file_cache_entry_d =
+ entry_d.mutable_file_specific_info()->mutable_cache_state();
+ file_cache_entry_d->set_is_present(true);
+ file_cache_entry_d->set_is_pinned(true);
+ file_cache_entry_d->set_is_dirty(false);
ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_d));
-
- // Entry E: pinned cache file.
+ const base::FilePath file_path_d = GetCacheFilePath(id_d);
+ ASSERT_TRUE(base::CopyFile(temp_file, file_path_d));
+
+ // Set removable flag.
+ FileAttributes flags = GetFileAttributes(file_path_d);
+ ASSERT_GE(flags, 0);
+ flags |= FS_NODUMP_FL;
+ base::File file_d(file_path_d, base::File::FLAG_OPEN | base::File::FLAG_READ);
+ ASSERT_EQ(ioctl(file_d.GetPlatformFile(), FS_IOC_SETFLAGS, &flags), 0);
+
+ // Entry E: there is no file; removed by cryptohome.
const std::string id_e = "id_e";
ResourceEntry entry_e;
entry_e.set_local_id(id_e);
FileCacheEntry* file_cache_entry_e =
entry_e.mutable_file_specific_info()->mutable_cache_state();
file_cache_entry_e->set_is_present(true);
- file_cache_entry_e->set_is_pinned(true);
+ file_cache_entry_e->set_is_pinned(false);
file_cache_entry_e->set_is_dirty(false);
ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_e));
- const base::FilePath old_file_path_e = old_cache_dir.AppendASCII(id_e);
- const base::FilePath new_file_path_e = new_cache_dir.AppendASCII(id_e);
- const base::FilePath link_path_e = link_dir.AppendASCII(id_e);
- ASSERT_TRUE(base::CopyFile(temp_file, old_file_path_e));
-
- // Entry F: dirty cache file.
+ const base::FilePath file_path_e = GetCacheFilePath(id_e);
+
+ // Entry F: there is a file, but metadata says not.
const std::string id_f = "id_f";
ResourceEntry entry_f;
entry_f.set_local_id(id_f);
- FileCacheEntry* file_cache_entry_f =
- entry_f.mutable_file_specific_info()->mutable_cache_state();
- file_cache_entry_f->set_is_present(true);
- file_cache_entry_f->set_is_pinned(false);
- file_cache_entry_f->set_is_dirty(true);
+ entry_f.mutable_file_specific_info()->mutable_cache_state()->set_is_present(
+ false);
ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_f));
- const base::FilePath old_file_path_f = old_cache_dir.AppendASCII(id_f);
- const base::FilePath new_file_path_f = new_cache_dir.AppendASCII(id_f);
- const base::FilePath link_path_f = link_dir.AppendASCII(id_f);
- ASSERT_TRUE(base::CopyFile(temp_file, old_file_path_f));
-
- // Entry G: partially migrated pinned cache file.
+ const base::FilePath file_path_f = GetCacheFilePath(id_f);
+ ASSERT_TRUE(base::CopyFile(temp_file, file_path_f));
+
+ // Entry G: no file nor metadata.
const std::string id_g = "id_g";
ResourceEntry entry_g;
entry_g.set_local_id(id_g);
- FileCacheEntry* file_cache_entry_g =
- entry_g.mutable_file_specific_info()->mutable_cache_state();
- file_cache_entry_g->set_is_present(true);
- file_cache_entry_g->set_is_pinned(true);
- file_cache_entry_g->set_is_dirty(false);
- ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_g));
- const base::FilePath old_file_path_g = old_cache_dir.AppendASCII(id_g);
- const base::FilePath new_file_path_g = new_cache_dir.AppendASCII(id_g);
- const base::FilePath link_path_g = link_dir.AppendASCII(id_g);
- ASSERT_TRUE(base::CopyFile(temp_file, old_file_path_g));
- ASSERT_EQ(0, link(old_file_path_g.AsUTF8Unsafe().c_str(),
- link_path_g.AsUTF8Unsafe().c_str()));
-
- // Entry H: pinned entry without cache file.
- const std::string id_h = "id_h";
- ResourceEntry entry_h;
- entry_h.set_local_id(id_h);
- FileCacheEntry* file_cache_entry_h =
- entry_h.mutable_file_specific_info()->mutable_cache_state();
- file_cache_entry_h->set_is_present(true);
- file_cache_entry_h->set_is_pinned(true);
- file_cache_entry_h->set_is_dirty(false);
- ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_h));
-
- // Entry I: already migrated pinned cache file.
- const std::string id_i = "id_i";
- ResourceEntry entry_i;
- entry_i.set_local_id(id_i);
- FileCacheEntry* file_cache_entry_i =
- entry_i.mutable_file_specific_info()->mutable_cache_state();
- file_cache_entry_i->set_is_present(true);
- file_cache_entry_i->set_is_pinned(true);
- file_cache_entry_i->set_is_dirty(false);
- ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_i));
- const base::FilePath new_file_path_i = new_cache_dir.AppendASCII(id_i);
- const base::FilePath link_path_i = link_dir.AppendASCII(id_i);
- ASSERT_TRUE(base::CopyFile(temp_file, new_file_path_i));
- ASSERT_EQ(0, link(new_file_path_i.AsUTF8Unsafe().c_str(),
- link_path_i.AsUTF8Unsafe().c_str()));
-
- // Run migration.
- ASSERT_TRUE(FileCache::MigrateCacheFiles(old_cache_dir, new_cache_dir,
- link_dir, metadata_storage_.get()));
+ entry_f.mutable_file_specific_info()->mutable_cache_state()->set_is_present(
+ false);
+ ASSERT_EQ(FILE_ERROR_OK, metadata_storage_->PutEntry(entry_f));
+
+ // Initialize fixes inconsistency between metadata and cache file attributes
+ // as well as adding specific file attributes to the cache directory.
+ ASSERT_TRUE(cache_->Initialize());
// Check result.
- EXPECT_FALSE(base::PathExists(old_file_path_a));
- EXPECT_TRUE(base::PathExists(new_file_path_a));
- EXPECT_EQ(1, GetNumberOfLinks(new_file_path_a));
- // MigrateCacheFiles doesn't delete invalid cache file.
- EXPECT_TRUE(base::PathExists(old_file_path_b));
- EXPECT_TRUE(base::PathExists(new_file_path_c));
- EXPECT_EQ(1, GetNumberOfLinks(new_file_path_c));
- EXPECT_FALSE(base::PathExists(old_file_path_e));
- EXPECT_TRUE(base::PathExists(new_file_path_e));
- EXPECT_TRUE(base::PathExists(link_path_e));
- EXPECT_EQ(2, GetNumberOfLinks(new_file_path_e));
- EXPECT_FALSE(base::PathExists(old_file_path_f));
- EXPECT_TRUE(base::PathExists(new_file_path_f));
- EXPECT_TRUE(base::PathExists(link_path_f));
- EXPECT_EQ(2, GetNumberOfLinks(new_file_path_f));
- EXPECT_FALSE(base::PathExists(old_file_path_g));
- EXPECT_TRUE(base::PathExists(new_file_path_g));
- EXPECT_TRUE(base::PathExists(link_path_g));
- EXPECT_EQ(2, GetNumberOfLinks(new_file_path_g));
- EXPECT_TRUE(base::PathExists(new_file_path_i));
- EXPECT_TRUE(base::PathExists(link_path_i));
- EXPECT_EQ(2, GetNumberOfLinks(new_file_path_i));
+ EXPECT_FALSE(HasRemovableFlag(file_path_a));
+ EXPECT_FALSE(HasRemovableFlag((file_path_b)));
+ EXPECT_TRUE(HasRemovableFlag((file_path_c)));
+ EXPECT_FALSE(HasRemovableFlag((file_path_d)));
+ EXPECT_FALSE(base::PathExists(file_path_f));
+
+ EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_e, &entry_e));
+ EXPECT_FALSE(entry_e.file_specific_info().cache_state().is_present());
+ EXPECT_EQ(FILE_ERROR_OK, metadata_storage_->GetEntry(id_f, &entry_f));
+ EXPECT_FALSE(entry_f.file_specific_info().cache_state().is_present());
+
+ // Check the cache dir has appropriate attributes.
+ EXPECT_TRUE(HasRemovableFlag((cache_files_dir_)));
+ EXPECT_GE(getxattr(cache_files_dir_.value().c_str(),
+ FileCache::kGCacheFilesAttribute, nullptr, 0), 0);
}
TEST_F(FileCacheTest, ClearAll) {
« no previous file with comments | « components/drive/chromeos/file_cache.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698