blob: 980e61b3d9eda1cb64aabe71b2e3cfd9490e7291 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "webkit/fileapi/local_file_system_operation.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "base/scoped_temp_dir.h"
#include "base/string_number_conversions.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/blob/shareable_file_reference.h"
#include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_file_util.h"
#include "webkit/fileapi/file_system_mount_point_provider.h"
#include "webkit/fileapi/file_system_quota_util.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/file_util_helper.h"
#include "webkit/fileapi/local_file_system_test_helper.h"
#include "webkit/fileapi/mock_file_change_observer.h"
#include "webkit/quota/quota_manager.h"
#include "webkit/quota/mock_quota_manager.h"
using quota::QuotaManager;
using quota::QuotaManagerProxy;
using webkit_blob::ShareableFileReference;
namespace fileapi {
namespace {
const int kFileOperationStatusNotSet = 1;
void AssertFileErrorEq(base::PlatformFileError expected,
base::PlatformFileError actual) {
ASSERT_EQ(expected, actual);
}
FilePath ASCIIToFilePath(const std::string& str) {
return FilePath().AppendASCII(str);
}
} // namespace (anonymous)
// Test class for LocalFileSystemOperation.
class LocalFileSystemOperationTest
: public testing::Test,
public base::SupportsWeakPtr<LocalFileSystemOperationTest> {
public:
LocalFileSystemOperationTest()
: status_(kFileOperationStatusNotSet),
next_unique_path_suffix_(0) {
EXPECT_TRUE(base_.CreateUniqueTempDir());
change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
}
LocalFileSystemOperation* operation();
int status() const { return status_; }
const base::PlatformFileInfo& info() const { return info_; }
const FilePath& path() const { return path_; }
const std::vector<base::FileUtilProxy::Entry>& entries() const {
return entries_;
}
const ShareableFileReference* shareable_file_ref() const {
return shareable_file_ref_;
}
virtual void SetUp() OVERRIDE;
virtual void TearDown() OVERRIDE;
protected:
// Common temp base for nondestructive uses.
ScopedTempDir base_;
quota::MockQuotaManager* quota_manager() {
return static_cast<quota::MockQuotaManager*>(quota_manager_.get());
}
quota::MockQuotaManagerProxy* quota_manager_proxy() {
return static_cast<quota::MockQuotaManagerProxy*>(
quota_manager_proxy_.get());
}
FileSystemFileUtil* file_util() {
return test_helper_.file_util();
}
const ChangeObserverList& change_observers() const {
return change_observers_;
}
MockFileChangeObserver* change_observer() {
return &change_observer_;
}
FileSystemOperationContext* NewContext() {
FileSystemOperationContext* context = test_helper_.NewOperationContext();
// Grant enough quota for all test cases.
context->set_allowed_bytes_growth(1000000);
return context;
}
FileSystemURL URLForPath(const FilePath& path) const {
return test_helper_.CreateURL(path);
}
FilePath PlatformPath(const FilePath& virtual_path) {
return test_helper_.GetLocalPath(virtual_path);
}
bool FileExists(const FilePath& virtual_path) {
FileSystemURL path = test_helper_.CreateURL(virtual_path);
scoped_ptr<FileSystemOperationContext> context(NewContext());
if (!FileUtilHelper::PathExists(context.get(), file_util(), path))
return false;
context.reset(NewContext());
return !FileUtilHelper::DirectoryExists(context.get(), file_util(), path);
}
bool DirectoryExists(const FilePath& virtual_path) {
FileSystemURL url = test_helper_.CreateURL(virtual_path);
scoped_ptr<FileSystemOperationContext> context(NewContext());
return FileUtilHelper::DirectoryExists(context.get(), file_util(), url);
}
FilePath CreateUniqueFileInDir(const FilePath& virtual_dir_path) {
FilePath file_name = FilePath::FromUTF8Unsafe(
"tmpfile-" + base::IntToString(next_unique_path_suffix_++));
FileSystemURL url = test_helper_.CreateURL(
virtual_dir_path.Append(file_name));
scoped_ptr<FileSystemOperationContext> context(NewContext());
bool created;
EXPECT_EQ(base::PLATFORM_FILE_OK,
file_util()->EnsureFileExists(context.get(), url, &created));
EXPECT_TRUE(created);
return url.path();
}
FilePath CreateUniqueDirInDir(const FilePath& virtual_dir_path) {
FilePath dir_name = FilePath::FromUTF8Unsafe(
"tmpdir-" + base::IntToString(next_unique_path_suffix_++));
FileSystemURL url = test_helper_.CreateURL(
virtual_dir_path.Append(dir_name));
scoped_ptr<FileSystemOperationContext> context(NewContext());
EXPECT_EQ(base::PLATFORM_FILE_OK,
file_util()->CreateDirectory(context.get(), url, false, true));
return url.path();
}
FilePath CreateUniqueDir() {
return CreateUniqueDirInDir(FilePath());
}
LocalFileSystemTestOriginHelper test_helper_;
// Callbacks for recording test results.
FileSystemOperation::StatusCallback RecordStatusCallback() {
return base::Bind(&LocalFileSystemOperationTest::DidFinish, AsWeakPtr());
}
FileSystemOperation::ReadDirectoryCallback
RecordReadDirectoryCallback() {
return base::Bind(&LocalFileSystemOperationTest::DidReadDirectory,
AsWeakPtr());
}
FileSystemOperation::GetMetadataCallback RecordMetadataCallback() {
return base::Bind(&LocalFileSystemOperationTest::DidGetMetadata,
AsWeakPtr());
}
FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback() {
return base::Bind(&LocalFileSystemOperationTest::DidCreateSnapshotFile,
AsWeakPtr());
}
void DidFinish(base::PlatformFileError status) {
status_ = status;
}
void DidReadDirectory(
base::PlatformFileError status,
const std::vector<base::FileUtilProxy::Entry>& entries,
bool /* has_more */) {
entries_ = entries;
status_ = status;
}
void DidGetMetadata(base::PlatformFileError status,
const base::PlatformFileInfo& info,
const FilePath& platform_path) {
info_ = info;
path_ = platform_path;
status_ = status;
}
void DidCreateSnapshotFile(
base::PlatformFileError status,
const base::PlatformFileInfo& info,
const FilePath& platform_path,
const scoped_refptr<ShareableFileReference>& shareable_file_ref) {
info_ = info;
path_ = platform_path;
status_ = status;
shareable_file_ref_ = shareable_file_ref;
}
static void DidGetUsageAndQuota(quota::QuotaStatusCode* status_out,
int64* usage_out,
int64* quota_out,
quota::QuotaStatusCode status,
int64 usage,
int64 quota) {
if (status_out)
*status_out = status;
if (usage_out)
*usage_out = usage;
if (quota_out)
*quota_out = quota;
}
void GetUsageAndQuota(int64* usage, int64* quota) {
quota::QuotaStatusCode status = quota::kQuotaStatusUnknown;
quota_manager_->GetUsageAndQuota(
test_helper_.origin(),
test_helper_.storage_type(),
base::Bind(&LocalFileSystemOperationTest::DidGetUsageAndQuota,
&status, usage, quota));
MessageLoop::current()->RunAllPending();
ASSERT_EQ(quota::kQuotaStatusOk, status);
}
void GenerateUniquePathInDir(const FilePath& dir,
FilePath* file_path,
int64* path_cost) {
int64 base_usage;
GetUsageAndQuota(&base_usage, NULL);
*file_path = CreateUniqueFileInDir(dir);
operation()->Remove(URLForPath(*file_path),
false /* recursive */,
base::Bind(&AssertFileErrorEq,
base::PLATFORM_FILE_OK));
MessageLoop::current()->RunAllPending();
int64 total_usage;
GetUsageAndQuota(&total_usage, NULL);
*path_cost = total_usage - base_usage;
}
void GrantQuotaForCurrentUsage() {
int64 usage;
GetUsageAndQuota(&usage, NULL);
quota_manager()->SetQuota(test_helper_.origin(),
test_helper_.storage_type(),
usage);
}
void AddQuota(int64 quota_delta) {
int64 quota;
GetUsageAndQuota(NULL, &quota);
quota_manager()->SetQuota(test_helper_.origin(),
test_helper_.storage_type(),
quota + quota_delta);
}
// For post-operation status.
int status_;
base::PlatformFileInfo info_;
FilePath path_;
std::vector<base::FileUtilProxy::Entry> entries_;
scoped_refptr<ShareableFileReference> shareable_file_ref_;
private:
MessageLoop message_loop_;
scoped_refptr<QuotaManager> quota_manager_;
scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;
MockFileChangeObserver change_observer_;
ChangeObserverList change_observers_;
int next_unique_path_suffix_;
DISALLOW_COPY_AND_ASSIGN(LocalFileSystemOperationTest);
};
void LocalFileSystemOperationTest::SetUp() {
FilePath base_dir = base_.path().AppendASCII("filesystem");
quota_manager_ = new quota::MockQuotaManager(
false /* is_incognito */, base_dir,
base::MessageLoopProxy::current(),
base::MessageLoopProxy::current(),
NULL /* special storage policy */);
quota_manager_proxy_ = new quota::MockQuotaManagerProxy(
quota_manager(),
base::MessageLoopProxy::current());
test_helper_.SetUp(base_dir,
false /* unlimited quota */,
quota_manager_proxy_.get(),
NULL);
}
void LocalFileSystemOperationTest::TearDown() {
// Let the client go away before dropping a ref of the quota manager proxy.
quota_manager_proxy()->SimulateQuotaManagerDestroyed();
quota_manager_ = NULL;
quota_manager_proxy_ = NULL;
test_helper_.TearDown();
}
LocalFileSystemOperation* LocalFileSystemOperationTest::operation() {
LocalFileSystemOperation* operation = test_helper_.NewOperation();
operation->operation_context()->set_change_observers(change_observers());
return operation;
}
TEST_F(LocalFileSystemOperationTest, TestMoveFailureSrcDoesntExist) {
FileSystemURL src(URLForPath(FilePath(FILE_PATH_LITERAL("a"))));
FileSystemURL dest(URLForPath(FilePath(FILE_PATH_LITERAL("b"))));
change_observer()->ResetCount();
operation()->Move(src, dest, RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestMoveFailureContainsPath) {
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_dir_path(CreateUniqueDirInDir(src_dir_path));
operation()->Move(URLForPath(src_dir_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestMoveFailureSrcDirExistsDestFile) {
// Src exists and is dir. Dest is a file.
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_dir_path(CreateUniqueDir());
FilePath dest_file_path(CreateUniqueFileInDir(dest_dir_path));
operation()->Move(URLForPath(src_dir_path), URLForPath(dest_file_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest,
TestMoveFailureSrcFileExistsDestNonEmptyDir) {
// Src exists and is a directory. Dest is a non-empty directory.
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_dir_path(CreateUniqueDir());
FilePath child_file_path(CreateUniqueFileInDir(dest_dir_path));
operation()->Move(URLForPath(src_dir_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestMoveFailureSrcFileExistsDestDir) {
// Src exists and is a file. Dest is a directory.
FilePath src_dir_path(CreateUniqueDir());
FilePath src_file_path(CreateUniqueFileInDir(src_dir_path));
FilePath dest_dir_path(CreateUniqueDir());
operation()->Move(URLForPath(src_file_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestMoveFailureDestParentDoesntExist) {
// Dest. parent path does not exist.
FilePath src_dir_path(CreateUniqueDir());
FilePath nonexisting_file = FilePath(FILE_PATH_LITERAL("NonexistingDir")).
Append(FILE_PATH_LITERAL("NonexistingFile"));
operation()->Move(URLForPath(src_dir_path), URLForPath(nonexisting_file),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcFileAndOverwrite) {
FilePath src_dir_path(CreateUniqueDir());
FilePath src_file_path(CreateUniqueFileInDir(src_dir_path));
FilePath dest_dir_path(CreateUniqueDir());
FilePath dest_file_path(CreateUniqueFileInDir(dest_dir_path));
operation()->Move(URLForPath(src_file_path), URLForPath(dest_file_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(FileExists(dest_file_path));
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
// Move is considered 'write' access (for both side), and won't be counted
// as read access.
EXPECT_EQ(0, quota_manager_proxy()->notify_storage_accessed_count());
}
TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcFileAndNew) {
FilePath src_dir_path(CreateUniqueDir());
FilePath src_file_path(CreateUniqueFileInDir(src_dir_path));
FilePath dest_dir_path(CreateUniqueDir());
FilePath dest_file_path(dest_dir_path.Append(FILE_PATH_LITERAL("NewFile")));
operation()->Move(URLForPath(src_file_path), URLForPath(dest_file_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(FileExists(dest_file_path));
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcDirAndOverwrite) {
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_dir_path(CreateUniqueDir());
operation()->Move(URLForPath(src_dir_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_FALSE(DirectoryExists(src_dir_path));
EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
EXPECT_TRUE(change_observer()->HasNoChange());
// Make sure we've overwritten but not moved the source under the |dest_dir|.
EXPECT_TRUE(DirectoryExists(dest_dir_path));
EXPECT_FALSE(DirectoryExists(
dest_dir_path.Append(VirtualPath::BaseName(src_dir_path))));
}
TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcDirAndNew) {
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_parent_dir_path(CreateUniqueDir());
FilePath dest_child_dir_path(dest_parent_dir_path.
Append(FILE_PATH_LITERAL("NewDirectory")));
operation()->Move(URLForPath(src_dir_path), URLForPath(dest_child_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_FALSE(DirectoryExists(src_dir_path));
EXPECT_TRUE(DirectoryExists(dest_child_dir_path));
EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcDirRecursive) {
FilePath src_dir_path(CreateUniqueDir());
FilePath child_dir_path(CreateUniqueDirInDir(src_dir_path));
FilePath grandchild_file_path(
CreateUniqueFileInDir(child_dir_path));
FilePath dest_dir_path(CreateUniqueDir());
operation()->Move(URLForPath(src_dir_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(DirectoryExists(dest_dir_path.Append(
VirtualPath::BaseName(child_dir_path))));
EXPECT_TRUE(FileExists(dest_dir_path.Append(
VirtualPath::BaseName(child_dir_path)).Append(
VirtualPath::BaseName(grandchild_file_path))));
EXPECT_EQ(3, change_observer()->get_and_reset_remove_directory_count());
EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopyFailureSrcDoesntExist) {
operation()->Copy(URLForPath(FilePath(FILE_PATH_LITERAL("a"))),
URLForPath(FilePath(FILE_PATH_LITERAL("b"))),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopyFailureContainsPath) {
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_dir_path(CreateUniqueDirInDir(src_dir_path));
operation()->Copy(URLForPath(src_dir_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopyFailureSrcDirExistsDestFile) {
// Src exists and is dir. Dest is a file.
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_dir_path(CreateUniqueDir());
FilePath dest_file_path(CreateUniqueFileInDir(dest_dir_path));
operation()->Copy(URLForPath(src_dir_path), URLForPath(dest_file_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest,
TestCopyFailureSrcFileExistsDestNonEmptyDir) {
// Src exists and is a directory. Dest is a non-empty directory.
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_dir_path(CreateUniqueDir());
FilePath child_file_path(CreateUniqueFileInDir(dest_dir_path));
operation()->Copy(URLForPath(src_dir_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopyFailureSrcFileExistsDestDir) {
// Src exists and is a file. Dest is a directory.
FilePath src_dir_path(CreateUniqueDir());
FilePath src_file_path(CreateUniqueFileInDir(src_dir_path));
FilePath dest_dir_path(CreateUniqueDir());
operation()->Copy(URLForPath(src_file_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopyFailureDestParentDoesntExist) {
// Dest. parent path does not exist.
FilePath src_dir_path(CreateUniqueDir());
FilePath nonexisting_path = FilePath(FILE_PATH_LITERAL("DontExistDir"));
file_util::EnsureEndsWithSeparator(&nonexisting_path);
FilePath nonexisting_file_path(nonexisting_path.Append(
FILE_PATH_LITERAL("DontExistFile")));
operation()->Copy(URLForPath(src_dir_path),
URLForPath(nonexisting_file_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopyFailureByQuota) {
base::PlatformFileInfo info;
FilePath src_dir_path(CreateUniqueDir());
FilePath src_file_path(CreateUniqueFileInDir(src_dir_path));
FilePath dest_dir_path(CreateUniqueDir());
FilePath dest_file_path;
int64 dest_path_cost;
GenerateUniquePathInDir(dest_dir_path, &dest_file_path, &dest_path_cost);
GrantQuotaForCurrentUsage();
AddQuota(6);
operation()->Truncate(URLForPath(src_file_path), 6,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
AddQuota(6 + dest_path_cost - 1);
EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(src_file_path), &info));
EXPECT_EQ(6, info.size);
operation()->Copy(URLForPath(src_file_path), URLForPath(dest_file_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
EXPECT_FALSE(FileExists(dest_file_path));
}
TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcFileAndOverwrite) {
FilePath src_dir_path(CreateUniqueDir());
FilePath src_file_path(CreateUniqueFileInDir(src_dir_path));
FilePath dest_dir_path(CreateUniqueDir());
FilePath dest_file_path(CreateUniqueFileInDir(dest_dir_path));
operation()->Copy(URLForPath(src_file_path), URLForPath(dest_file_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(FileExists(dest_file_path));
EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcFileAndNew) {
FilePath src_dir_path(CreateUniqueDir());
FilePath src_file_path(CreateUniqueFileInDir(src_dir_path));
FilePath dest_dir_path(CreateUniqueDir());
FilePath dest_file_path(dest_dir_path.Append(FILE_PATH_LITERAL("NewFile")));
operation()->Copy(URLForPath(src_file_path), URLForPath(dest_file_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(FileExists(dest_file_path));
EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcDirAndOverwrite) {
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_dir_path(CreateUniqueDir());
operation()->Copy(URLForPath(src_dir_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
// Make sure we've overwritten but not copied the source under the |dest_dir|.
EXPECT_TRUE(DirectoryExists(dest_dir_path));
EXPECT_FALSE(DirectoryExists(
dest_dir_path.Append(VirtualPath::BaseName(src_dir_path))));
EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcDirAndNew) {
FilePath src_dir_path(CreateUniqueDir());
FilePath dest_parent_dir_path(CreateUniqueDir());
FilePath dest_child_dir_path(dest_parent_dir_path.
Append(FILE_PATH_LITERAL("NewDirectory")));
operation()->Copy(URLForPath(src_dir_path), URLForPath(dest_child_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(DirectoryExists(dest_child_dir_path));
EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcDirRecursive) {
FilePath src_dir_path(CreateUniqueDir());
FilePath child_dir_path(CreateUniqueDirInDir(src_dir_path));
FilePath grandchild_file_path(
CreateUniqueFileInDir(child_dir_path));
FilePath dest_dir_path(CreateUniqueDir());
operation()->Copy(URLForPath(src_dir_path), URLForPath(dest_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(DirectoryExists(dest_dir_path.Append(
VirtualPath::BaseName(child_dir_path))));
EXPECT_TRUE(FileExists(dest_dir_path.Append(
VirtualPath::BaseName(child_dir_path)).Append(
VirtualPath::BaseName(grandchild_file_path))));
EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCopyInForeignFileSuccess) {
FilePath src_local_disk_file_path;
file_util::CreateTemporaryFile(&src_local_disk_file_path);
const char test_data[] = "foo";
int data_size = ARRAYSIZE_UNSAFE(test_data);
file_util::WriteFile(src_local_disk_file_path, test_data, data_size);
FilePath dest_dir_path(CreateUniqueDir());
FilePath dest_file_path(dest_dir_path.Append(
src_local_disk_file_path.BaseName()));
FileSystemURL dest_file_url = URLForPath(dest_file_path);
int64 before_usage;
GetUsageAndQuota(&before_usage, NULL);
// Check that the file copied and corresponding usage increased.
operation()->CopyInForeignFile(src_local_disk_file_path,
dest_file_url,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(1, change_observer()->create_file_count());
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(FileExists(dest_file_path));
int64 after_usage;
GetUsageAndQuota(&after_usage, NULL);
EXPECT_GT(after_usage, before_usage);
// Compare contents of src and copied file.
char buffer[100];
EXPECT_EQ(data_size, file_util::ReadFile(PlatformPath(dest_file_path),
buffer, data_size));
for (int i = 0; i < data_size; ++i)
EXPECT_EQ(test_data[i], buffer[i]);
}
TEST_F(LocalFileSystemOperationTest, TestCopyInForeignFileFailureByQuota) {
FilePath src_local_disk_file_path;
file_util::CreateTemporaryFile(&src_local_disk_file_path);
const char test_data[] = "foo";
file_util::WriteFile(src_local_disk_file_path, test_data,
ARRAYSIZE_UNSAFE(test_data));
FilePath dest_dir_path(CreateUniqueDir());
FilePath dest_file_path(dest_dir_path.Append(
src_local_disk_file_path.BaseName()));
FileSystemURL dest_file_url = URLForPath(dest_file_path);
// Set quota of 0 which should force copy to fail by quota.
quota_manager()->SetQuota(dest_file_url.origin(),
test_helper_.storage_type(),
static_cast<int64>(0));
operation()->CopyInForeignFile(src_local_disk_file_path,
dest_file_url,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_TRUE(!FileExists(dest_file_path));
EXPECT_EQ(0, change_observer()->create_file_count());
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
}
TEST_F(LocalFileSystemOperationTest, TestCreateFileFailure) {
// Already existing file and exclusive true.
FilePath dir_path(CreateUniqueDir());
FilePath file_path(CreateUniqueFileInDir(dir_path));
operation()->CreateFile(URLForPath(file_path), true,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCreateFileSuccessFileExists) {
// Already existing file and exclusive false.
FilePath dir_path(CreateUniqueDir());
FilePath file_path(CreateUniqueFileInDir(dir_path));
operation()->CreateFile(URLForPath(file_path), false,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(FileExists(file_path));
// The file was already there; did nothing.
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCreateFileSuccessExclusive) {
// File doesn't exist but exclusive is true.
FilePath dir_path(CreateUniqueDir());
FilePath file_path(dir_path.Append(FILE_PATH_LITERAL("FileDoesntExist")));
operation()->CreateFile(URLForPath(file_path), true,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(FileExists(file_path));
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
}
TEST_F(LocalFileSystemOperationTest, TestCreateFileSuccessFileDoesntExist) {
// Non existing file.
FilePath dir_path(CreateUniqueDir());
FilePath file_path(dir_path.Append(FILE_PATH_LITERAL("FileDoesntExist")));
operation()->CreateFile(URLForPath(file_path), false,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
}
TEST_F(LocalFileSystemOperationTest,
TestCreateDirFailureDestParentDoesntExist) {
// Dest. parent path does not exist.
FilePath nonexisting_path(FilePath(
FILE_PATH_LITERAL("DirDoesntExist")));
FilePath nonexisting_file_path(nonexisting_path.Append(
FILE_PATH_LITERAL("FileDoesntExist")));
operation()->CreateDirectory(URLForPath(nonexisting_file_path), false, false,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCreateDirFailureDirExists) {
// Exclusive and dir existing at path.
FilePath src_dir_path(CreateUniqueDir());
operation()->CreateDirectory(URLForPath(src_dir_path), true, false,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCreateDirFailureFileExists) {
// Exclusive true and file existing at path.
FilePath dir_path(CreateUniqueDir());
FilePath file_path(CreateUniqueFileInDir(dir_path));
operation()->CreateDirectory(URLForPath(file_path), true, false,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestCreateDirSuccess) {
// Dir exists and exclusive is false.
FilePath dir_path(CreateUniqueDir());
operation()->CreateDirectory(URLForPath(dir_path), false, false,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(change_observer()->HasNoChange());
// Dir doesn't exist.
FilePath nonexisting_dir_path(FilePath(
FILE_PATH_LITERAL("nonexistingdir")));
operation()->CreateDirectory(URLForPath(nonexisting_dir_path), false, false,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(DirectoryExists(nonexisting_dir_path));
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
}
TEST_F(LocalFileSystemOperationTest, TestCreateDirSuccessExclusive) {
// Dir doesn't exist.
FilePath nonexisting_dir_path(FilePath(
FILE_PATH_LITERAL("nonexistingdir")));
operation()->CreateDirectory(URLForPath(nonexisting_dir_path), true, false,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(DirectoryExists(nonexisting_dir_path));
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestExistsAndMetadataFailure) {
FilePath nonexisting_dir_path(FilePath(
FILE_PATH_LITERAL("nonexistingdir")));
operation()->GetMetadata(URLForPath(nonexisting_dir_path),
RecordMetadataCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
operation()->FileExists(URLForPath(nonexisting_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
file_util::EnsureEndsWithSeparator(&nonexisting_dir_path);
operation()->DirectoryExists(URLForPath(nonexisting_dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestExistsAndMetadataSuccess) {
FilePath dir_path(CreateUniqueDir());
int read_access = 0;
operation()->DirectoryExists(URLForPath(dir_path),
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
++read_access;
operation()->GetMetadata(URLForPath(dir_path), RecordMetadataCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(info().is_directory);
EXPECT_EQ(FilePath(), path());
++read_access;
FilePath file_path(CreateUniqueFileInDir(dir_path));
operation()->FileExists(URLForPath(file_path), RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
++read_access;
operation()->GetMetadata(URLForPath(file_path), RecordMetadataCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_FALSE(info().is_directory);
EXPECT_EQ(PlatformPath(file_path), path());
++read_access;
EXPECT_EQ(read_access,
quota_manager_proxy()->notify_storage_accessed_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestTypeMismatchErrors) {
FilePath dir_path(CreateUniqueDir());
operation()->FileExists(URLForPath(dir_path), RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE, status());
FilePath file_path(CreateUniqueFileInDir(dir_path));
ASSERT_FALSE(file_path.empty());
operation()->DirectoryExists(URLForPath(file_path), RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, status());
}
TEST_F(LocalFileSystemOperationTest, TestReadDirFailure) {
// Path doesn't exist
FilePath nonexisting_dir_path(FilePath(
FILE_PATH_LITERAL("NonExistingDir")));
file_util::EnsureEndsWithSeparator(&nonexisting_dir_path);
operation()->ReadDirectory(URLForPath(nonexisting_dir_path),
RecordReadDirectoryCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
// File exists.
FilePath dir_path(CreateUniqueDir());
FilePath file_path(CreateUniqueFileInDir(dir_path));
operation()->ReadDirectory(URLForPath(file_path),
RecordReadDirectoryCallback());
MessageLoop::current()->RunAllPending();
// TODO(kkanetkar) crbug.com/54309 to change the error code.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestReadDirSuccess) {
// parent_dir
// | |
// child_dir child_file
// Verify reading parent_dir.
FilePath parent_dir_path(CreateUniqueDir());
FilePath child_file_path(CreateUniqueFileInDir(parent_dir_path));
FilePath child_dir_path(CreateUniqueDirInDir(parent_dir_path));
ASSERT_FALSE(child_dir_path.empty());
operation()->ReadDirectory(URLForPath(parent_dir_path),
RecordReadDirectoryCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_EQ(2u, entries().size());
for (size_t i = 0; i < entries().size(); ++i) {
if (entries()[i].is_directory) {
EXPECT_EQ(VirtualPath::BaseName(child_dir_path).value(),
entries()[i].name);
} else {
EXPECT_EQ(VirtualPath::BaseName(child_file_path).value(),
entries()[i].name);
}
}
EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestRemoveFailure) {
// Path doesn't exist.
FilePath nonexisting_path(FilePath(
FILE_PATH_LITERAL("NonExistingDir")));
file_util::EnsureEndsWithSeparator(&nonexisting_path);
operation()->Remove(URLForPath(nonexisting_path), false /* recursive */,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
// It's an error to try to remove a non-empty directory if recursive flag
// is false.
// parent_dir
// | |
// child_dir child_file
// Verify deleting parent_dir.
FilePath parent_dir_path(CreateUniqueDir());
FilePath child_file_path(CreateUniqueFileInDir(parent_dir_path));
FilePath child_dir_path(CreateUniqueDirInDir(parent_dir_path));
ASSERT_FALSE(child_dir_path.empty());
operation()->Remove(URLForPath(parent_dir_path), false /* recursive */,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY,
status());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestRemoveSuccess) {
FilePath empty_dir_path(CreateUniqueDir());
EXPECT_TRUE(DirectoryExists(empty_dir_path));
operation()->Remove(URLForPath(empty_dir_path), false /* recursive */,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_FALSE(DirectoryExists(empty_dir_path));
EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
EXPECT_TRUE(change_observer()->HasNoChange());
// Removing a non-empty directory with recursive flag == true should be ok.
// parent_dir
// | |
// child_dir child_file
// Verify deleting parent_dir.
FilePath parent_dir_path(CreateUniqueDir());
FilePath child_file_path(CreateUniqueFileInDir(parent_dir_path));
FilePath child_dir_path(CreateUniqueDirInDir(parent_dir_path));
ASSERT_FALSE(child_dir_path.empty());
operation()->Remove(URLForPath(parent_dir_path), true /* recursive */,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_FALSE(DirectoryExists(parent_dir_path));
// Remove is not a 'read' access.
EXPECT_EQ(0, quota_manager_proxy()->notify_storage_accessed_count());
EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(LocalFileSystemOperationTest, TestTruncate) {
FilePath dir_path(CreateUniqueDir());
FilePath file_path(CreateUniqueFileInDir(dir_path));
char test_data[] = "test data";
int data_size = static_cast<int>(sizeof(test_data));
EXPECT_EQ(data_size,
file_util::WriteFile(PlatformPath(file_path),
test_data, data_size));
// Check that its length is the size of the data written.
operation()->GetMetadata(URLForPath(file_path), RecordMetadataCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_FALSE(info().is_directory);
EXPECT_EQ(data_size, info().size);
// Extend the file by truncating it.
int length = 17;
operation()->Truncate(URLForPath(file_path), length, RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
// Check that its length is now 17 and that it's all zeroes after the test
// data.
base::PlatformFileInfo info;
EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(file_path), &info));
EXPECT_EQ(length, info.size);
char data[100];
EXPECT_EQ(length, file_util::ReadFile(PlatformPath(file_path), data, length));
for (int i = 0; i < length; ++i) {
if (i < static_cast<int>(sizeof(test_data)))
EXPECT_EQ(test_data[i], data[i]);
else
EXPECT_EQ(0, data[i]);
}
// Shorten the file by truncating it.
length = 3;
operation()->Truncate(URLForPath(file_path), length, RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
// Check that its length is now 3 and that it contains only bits of test data.
EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(file_path), &info));
EXPECT_EQ(length, info.size);
EXPECT_EQ(length, file_util::ReadFile(PlatformPath(file_path), data, length));
for (int i = 0; i < length; ++i)
EXPECT_EQ(test_data[i], data[i]);
// Truncate is not a 'read' access. (Here expected access count is 1
// since we made 1 read access for GetMetadata.)
EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
}
TEST_F(LocalFileSystemOperationTest, TestTruncateFailureByQuota) {
base::PlatformFileInfo info;
FilePath dir_path(CreateUniqueDir());
FilePath file_path(CreateUniqueFileInDir(dir_path));
GrantQuotaForCurrentUsage();
AddQuota(10);
operation()->Truncate(URLForPath(file_path), 10, RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(file_path), &info));
EXPECT_EQ(10, info.size);
operation()->Truncate(URLForPath(file_path), 11, RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
EXPECT_TRUE(change_observer()->HasNoChange());
EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(file_path), &info));
EXPECT_EQ(10, info.size);
}
TEST_F(LocalFileSystemOperationTest, TestTouchFile) {
FilePath file_path(CreateUniqueFileInDir(FilePath()));
FilePath platform_path = PlatformPath(file_path);
base::PlatformFileInfo info;
EXPECT_TRUE(file_util::GetFileInfo(platform_path, &info));
EXPECT_FALSE(info.is_directory);
EXPECT_EQ(0, info.size);
const base::Time last_modified = info.last_modified;
const base::Time last_accessed = info.last_accessed;
const base::Time new_modified_time = base::Time::UnixEpoch();
const base::Time new_accessed_time = new_modified_time +
base::TimeDelta::FromHours(77);
ASSERT_NE(last_modified, new_modified_time);
ASSERT_NE(last_accessed, new_accessed_time);
operation()->TouchFile(
URLForPath(file_path), new_accessed_time, new_modified_time,
RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_TRUE(change_observer()->HasNoChange());
EXPECT_TRUE(file_util::GetFileInfo(platform_path, &info));
// We compare as time_t here to lower our resolution, to avoid false
// negatives caused by conversion to the local filesystem's native
// representation and back.
EXPECT_EQ(new_modified_time.ToTimeT(), info.last_modified.ToTimeT());
EXPECT_EQ(new_accessed_time.ToTimeT(), info.last_accessed.ToTimeT());
}
TEST_F(LocalFileSystemOperationTest, TestCreateSnapshotFile) {
FilePath dir_path(CreateUniqueDir());
// Create a file for the testing.
operation()->DirectoryExists(URLForPath(dir_path),
RecordStatusCallback());
FilePath file_path(CreateUniqueFileInDir(dir_path));
operation()->FileExists(URLForPath(file_path), RecordStatusCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
// See if we can get a 'snapshot' file info for the file.
// Since LocalFileSystemOperation assumes the file exists in the local
// directory it should just returns the same metadata and platform_path
// as the file itself.
operation()->CreateSnapshotFile(URLForPath(file_path),
RecordSnapshotFileCallback());
MessageLoop::current()->RunAllPending();
EXPECT_EQ(base::PLATFORM_FILE_OK, status());
EXPECT_FALSE(info().is_directory);
EXPECT_EQ(PlatformPath(file_path), path());
EXPECT_TRUE(change_observer()->HasNoChange());
// The FileSystemOpration implementation does not create a
// shareable file reference.
EXPECT_EQ(NULL, shareable_file_ref());
}
} // namespace fileapi