diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-23 18:40:57 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-23 18:40:57 +0000 |
commit | 77e07b84f56ef033bb2a1dc6a6578b393868517a (patch) | |
tree | d646452e73d720f5eee8943716ad5f9668005845 /base | |
parent | 16fca9b8a9e129a2bc50bc39fa3d2b33db64efdb (diff) | |
download | chromium_src-77e07b84f56ef033bb2a1dc6a6578b393868517a.zip chromium_src-77e07b84f56ef033bb2a1dc6a6578b393868517a.tar.gz chromium_src-77e07b84f56ef033bb2a1dc6a6578b393868517a.tar.bz2 |
Convert MessageLoopProxy to TaskRunner in FileUtilProxy
Also adding unittests to FileUtilProxy.
BUG=123558,77454
TEST=FileUtilProxyTest.*
Review URL: http://codereview.chromium.org/10095028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@133484 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gyp | 1 | ||||
-rw-r--r-- | base/file_util_proxy.cc | 86 | ||||
-rw-r--r-- | base/file_util_proxy.h | 36 | ||||
-rw-r--r-- | base/file_util_proxy_unittest.cc | 407 |
4 files changed, 469 insertions, 61 deletions
diff --git a/base/base.gyp b/base/base.gyp index a7108af..9126900 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -154,6 +154,7 @@ 'environment_unittest.cc', 'file_descriptor_shuffle_unittest.cc', 'file_path_unittest.cc', + 'file_util_proxy_unittest.cc', 'file_util_unittest.cc', 'file_version_info_unittest.cc', 'gmock_unittest.cc', diff --git a/base/file_util_proxy.cc b/base/file_util_proxy.cc index 25d1718..62ac2e4 100644 --- a/base/file_util_proxy.cc +++ b/base/file_util_proxy.cc @@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/file_util.h" -#include "base/message_loop_proxy.h" +#include "base/task_runner.h" #include "base/task_runner_util.h" namespace base { @@ -23,9 +23,9 @@ void CallWithTranslatedParameter(const FileUtilProxy::StatusCallback& callback, // Helper classes or routines for individual methods. class CreateOrOpenHelper { public: - CreateOrOpenHelper(MessageLoopProxy* message_loop_proxy, + CreateOrOpenHelper(TaskRunner* task_runner, const FileUtilProxy::CloseTask& close_task) - : message_loop_proxy_(message_loop_proxy), + : task_runner_(task_runner), close_task_(close_task), file_handle_(kInvalidPlatformFileValue), created_(false), @@ -33,7 +33,7 @@ class CreateOrOpenHelper { ~CreateOrOpenHelper() { if (file_handle_ != kInvalidPlatformFileValue) { - message_loop_proxy_->PostTask( + task_runner_->PostTask( FROM_HERE, base::Bind(base::IgnoreResult(close_task_), file_handle_)); } @@ -49,7 +49,7 @@ class CreateOrOpenHelper { } private: - scoped_refptr<MessageLoopProxy> message_loop_proxy_; + scoped_refptr<TaskRunner> task_runner_; FileUtilProxy::CloseTask close_task_; PlatformFile file_handle_; bool created_; @@ -59,14 +59,14 @@ class CreateOrOpenHelper { class CreateTemporaryHelper { public: - CreateTemporaryHelper(MessageLoopProxy* message_loop_proxy) - : message_loop_proxy_(message_loop_proxy), + CreateTemporaryHelper(TaskRunner* task_runner) + : task_runner_(task_runner), file_handle_(kInvalidPlatformFileValue), error_(PLATFORM_FILE_OK) {} ~CreateTemporaryHelper() { if (file_handle_ != kInvalidPlatformFileValue) { - FileUtilProxy::Close(message_loop_proxy_, file_handle_, + FileUtilProxy::Close(task_runner_, file_handle_, FileUtilProxy::StatusCallback()); } } @@ -92,7 +92,7 @@ class CreateTemporaryHelper { } private: - scoped_refptr<MessageLoopProxy> message_loop_proxy_; + scoped_refptr<TaskRunner> task_runner_; PlatformFile file_handle_; FilePath file_path_; PlatformFileError error_; @@ -224,11 +224,11 @@ PlatformFileError DeleteAdapter(const FilePath& file_path, bool recursive) { // static bool FileUtilProxy::CreateOrOpen( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const FilePath& file_path, int file_flags, const CreateOrOpenCallback& callback) { return RelayCreateOrOpen( - message_loop_proxy, + task_runner, base::Bind(&CreateOrOpenAdapter, file_path, file_flags), base::Bind(&CloseAdapter), callback); @@ -236,11 +236,11 @@ bool FileUtilProxy::CreateOrOpen( // static bool FileUtilProxy::CreateTemporary( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, int additional_file_flags, const CreateTemporaryCallback& callback) { - CreateTemporaryHelper* helper = new CreateTemporaryHelper(message_loop_proxy); - return message_loop_proxy->PostTaskAndReply( + CreateTemporaryHelper* helper = new CreateTemporaryHelper(task_runner); + return task_runner->PostTaskAndReply( FROM_HERE, Bind(&CreateTemporaryHelper::RunWork, Unretained(helper), additional_file_flags), @@ -249,11 +249,11 @@ bool FileUtilProxy::CreateTemporary( // static bool FileUtilProxy::Close( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, base::PlatformFile file_handle, const StatusCallback& callback) { return RelayClose( - message_loop_proxy, + task_runner, base::Bind(&CloseAdapter), file_handle, callback); } @@ -261,11 +261,11 @@ bool FileUtilProxy::Close( // Retrieves the information about a file. It is invalid to pass NULL for the // callback. bool FileUtilProxy::GetFileInfo( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const FilePath& file_path, const GetFileInfoCallback& callback) { GetFileInfoHelper* helper = new GetFileInfoHelper; - return message_loop_proxy->PostTaskAndReply( + return task_runner->PostTaskAndReply( FROM_HERE, Bind(&GetFileInfoHelper::RunWorkForFilePath, Unretained(helper), file_path), @@ -274,11 +274,11 @@ bool FileUtilProxy::GetFileInfo( // static bool FileUtilProxy::GetFileInfoFromPlatformFile( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, const GetFileInfoCallback& callback) { GetFileInfoHelper* helper = new GetFileInfoHelper; - return message_loop_proxy->PostTaskAndReply( + return task_runner->PostTaskAndReply( FROM_HERE, Bind(&GetFileInfoHelper::RunWorkForPlatformFile, Unretained(helper), file), @@ -286,30 +286,30 @@ bool FileUtilProxy::GetFileInfoFromPlatformFile( } // static -bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy, +bool FileUtilProxy::Delete(TaskRunner* task_runner, const FilePath& file_path, bool recursive, const StatusCallback& callback) { return RelayFileTask( - message_loop_proxy, FROM_HERE, + task_runner, FROM_HERE, Bind(&DeleteAdapter, file_path, recursive), callback); } // static bool FileUtilProxy::RecursiveDelete( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const FilePath& file_path, const StatusCallback& callback) { return RelayFileTask( - message_loop_proxy, FROM_HERE, + task_runner, FROM_HERE, Bind(&DeleteAdapter, file_path, true /* recursive */), callback); } // static bool FileUtilProxy::Read( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, int64 offset, int bytes_to_read, @@ -318,7 +318,7 @@ bool FileUtilProxy::Read( return false; } ReadHelper* helper = new ReadHelper(bytes_to_read); - return message_loop_proxy->PostTaskAndReply( + return task_runner->PostTaskAndReply( FROM_HERE, Bind(&ReadHelper::RunWork, Unretained(helper), file, offset), Bind(&ReadHelper::Reply, Owned(helper), callback)); @@ -326,7 +326,7 @@ bool FileUtilProxy::Read( // static bool FileUtilProxy::Write( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, int64 offset, const char* buffer, @@ -336,7 +336,7 @@ bool FileUtilProxy::Write( return false; } WriteHelper* helper = new WriteHelper(buffer, bytes_to_write); - return message_loop_proxy->PostTaskAndReply( + return task_runner->PostTaskAndReply( FROM_HERE, Bind(&WriteHelper::RunWork, Unretained(helper), file, offset), Bind(&WriteHelper::Reply, Owned(helper), callback)); @@ -344,13 +344,13 @@ bool FileUtilProxy::Write( // static bool FileUtilProxy::Touch( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, const Time& last_access_time, const Time& last_modified_time, const StatusCallback& callback) { return base::PostTaskAndReplyWithResult( - message_loop_proxy, + task_runner, FROM_HERE, Bind(&TouchPlatformFile, file, last_access_time, last_modified_time), @@ -359,13 +359,13 @@ bool FileUtilProxy::Touch( // static bool FileUtilProxy::Touch( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const FilePath& file_path, const Time& last_access_time, const Time& last_modified_time, const StatusCallback& callback) { return base::PostTaskAndReplyWithResult( - message_loop_proxy, + task_runner, FROM_HERE, Bind(&file_util::TouchFile, file_path, last_access_time, last_modified_time), @@ -374,12 +374,12 @@ bool FileUtilProxy::Touch( // static bool FileUtilProxy::Truncate( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, int64 length, const StatusCallback& callback) { return base::PostTaskAndReplyWithResult( - message_loop_proxy, + task_runner, FROM_HERE, Bind(&TruncatePlatformFile, file, length), Bind(&CallWithTranslatedParameter, callback)); @@ -387,11 +387,11 @@ bool FileUtilProxy::Truncate( // static bool FileUtilProxy::Flush( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, const StatusCallback& callback) { return base::PostTaskAndReplyWithResult( - message_loop_proxy, + task_runner, FROM_HERE, Bind(&FlushPlatformFile, file), Bind(&CallWithTranslatedParameter, callback)); @@ -399,23 +399,23 @@ bool FileUtilProxy::Flush( // static bool FileUtilProxy::RelayFileTask( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const tracked_objects::Location& from_here, const FileTask& file_task, const StatusCallback& callback) { return base::PostTaskAndReplyWithResult( - message_loop_proxy, from_here, file_task, callback); + task_runner, from_here, file_task, callback); } // static bool FileUtilProxy::RelayCreateOrOpen( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const CreateOrOpenTask& open_task, const CloseTask& close_task, const CreateOrOpenCallback& callback) { CreateOrOpenHelper* helper = new CreateOrOpenHelper( - message_loop_proxy, close_task); - return message_loop_proxy->PostTaskAndReply( + task_runner, close_task); + return task_runner->PostTaskAndReply( FROM_HERE, Bind(&CreateOrOpenHelper::RunWork, Unretained(helper), open_task), Bind(&CreateOrOpenHelper::Reply, Owned(helper), callback)); @@ -423,12 +423,12 @@ bool FileUtilProxy::RelayCreateOrOpen( // static bool FileUtilProxy::RelayClose( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const CloseTask& close_task, PlatformFile file_handle, const StatusCallback& callback) { return base::PostTaskAndReplyWithResult( - message_loop_proxy, FROM_HERE, Bind(close_task, file_handle), callback); + task_runner, FROM_HERE, Bind(close_task, file_handle), callback); } } // namespace base diff --git a/base/file_util_proxy.h b/base/file_util_proxy.h index 0b2cae5..954c451 100644 --- a/base/file_util_proxy.h +++ b/base/file_util_proxy.h @@ -17,7 +17,7 @@ namespace base { -class MessageLoopProxy; +class TaskRunner; class Time; // This class provides asynchronous access to common file routines. @@ -59,7 +59,7 @@ class BASE_EXPORT FileUtilProxy { // callback. If PLATFORM_FILE_CREATE is set in |file_flags| it always tries to // create a new file at the given |file_path| and calls back with // PLATFORM_FILE_ERROR_FILE_EXISTS if the |file_path| already exists. - static bool CreateOrOpen(scoped_refptr<MessageLoopProxy> message_loop_proxy, + static bool CreateOrOpen(TaskRunner* task_runner, const FilePath& file_path, int file_flags, const CreateOrOpenCallback& callback); @@ -73,44 +73,44 @@ class BASE_EXPORT FileUtilProxy { // Set |additional_file_flags| to 0 for synchronous writes and set to // base::PLATFORM_FILE_ASYNC to support asynchronous file operations. static bool CreateTemporary( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, int additional_file_flags, const CreateTemporaryCallback& callback); // Close the given file handle. - static bool Close(scoped_refptr<MessageLoopProxy> message_loop_proxy, + static bool Close(TaskRunner* task_runner, PlatformFile, const StatusCallback& callback); // Retrieves the information about a file. It is invalid to pass a null // callback. static bool GetFileInfo( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const FilePath& file_path, const GetFileInfoCallback& callback); static bool GetFileInfoFromPlatformFile( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, const GetFileInfoCallback& callback); // Deletes a file or a directory. // It is an error to delete a non-empty directory with recursive=false. - static bool Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy, + static bool Delete(TaskRunner* task_runner, const FilePath& file_path, bool recursive, const StatusCallback& callback); // Deletes a directory and all of its contents. static bool RecursiveDelete( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const FilePath& file_path, const StatusCallback& callback); // Reads from a file. On success, the file pointer is moved to position // |offset + bytes_to_read| in the file. The callback can be null. static bool Read( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, int64 offset, int bytes_to_read, @@ -121,7 +121,7 @@ class BASE_EXPORT FileUtilProxy { // |offset + bytes_to_write| in the file. The callback can be null. // |bytes_to_write| must be greater than zero. static bool Write( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, int64 offset, const char* buffer, @@ -130,7 +130,7 @@ class BASE_EXPORT FileUtilProxy { // Touches a file. The callback can be null. static bool Touch( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, const Time& last_access_time, const Time& last_modified_time, @@ -138,7 +138,7 @@ class BASE_EXPORT FileUtilProxy { // Touches a file. The callback can be null. static bool Touch( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const FilePath& file_path, const Time& last_access_time, const Time& last_modified_time, @@ -148,7 +148,7 @@ class BASE_EXPORT FileUtilProxy { // current length of the file, the file will be extended with zeroes. // The callback can be null. static bool Truncate( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, int64 length, const StatusCallback& callback); @@ -157,32 +157,32 @@ class BASE_EXPORT FileUtilProxy { // current length of the file, the file will be extended with zeroes. // The callback can be null. static bool Truncate( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const FilePath& path, int64 length, const StatusCallback& callback); // Flushes a file. The callback can be null. static bool Flush( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, PlatformFile file, const StatusCallback& callback); // Relay helpers. static bool RelayFileTask( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const tracked_objects::Location& from_here, const FileTask& task, const StatusCallback& callback); static bool RelayCreateOrOpen( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const CreateOrOpenTask& open_task, const CloseTask& close_task, const CreateOrOpenCallback& callback); static bool RelayClose( - scoped_refptr<MessageLoopProxy> message_loop_proxy, + TaskRunner* task_runner, const CloseTask& close_task, PlatformFile, const StatusCallback& callback); diff --git a/base/file_util_proxy_unittest.cc b/base/file_util_proxy_unittest.cc new file mode 100644 index 0000000..402385a --- /dev/null +++ b/base/file_util_proxy_unittest.cc @@ -0,0 +1,407 @@ +// 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 "base/file_util_proxy.h" + +#include <map> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/weak_ptr.h" +#include "base/message_loop.h" +#include "base/platform_file.h" +#include "base/scoped_temp_dir.h" +#include "base/threading/thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +class FileUtilProxyTest : public testing::Test { + public: + FileUtilProxyTest() + : message_loop_(MessageLoop::TYPE_IO), + file_thread_("FileUtilProxyTestFileThread"), + error_(PLATFORM_FILE_OK), + created_(false), + file_(kInvalidPlatformFileValue), + bytes_written_(-1), + weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} + + virtual void SetUp() OVERRIDE { + ASSERT_TRUE(dir_.CreateUniqueTempDir()); + ASSERT_TRUE(file_thread_.Start()); + } + + virtual void TearDown() OVERRIDE { + if (file_ != kInvalidPlatformFileValue) + ClosePlatformFile(file_); + } + + void DidFinish(PlatformFileError error) { + error_ = error; + MessageLoop::current()->Quit(); + } + + void DidCreateOrOpen(PlatformFileError error, + PassPlatformFile file, + bool created) { + error_ = error; + file_ = file.ReleaseValue(); + created_ = created; + MessageLoop::current()->Quit(); + } + + void DidCreateTemporary(PlatformFileError error, + PassPlatformFile file, + const FilePath& path) { + error_ = error; + file_ = file.ReleaseValue(); + path_ = path; + MessageLoop::current()->Quit(); + } + + void DidGetFileInfo(PlatformFileError error, + const PlatformFileInfo& file_info) { + error_ = error; + file_info_ = file_info; + MessageLoop::current()->Quit(); + } + + void DidRead(PlatformFileError error, + const char* data, + int bytes_read) { + error_ = error; + buffer_.resize(bytes_read); + memcpy(&buffer_[0], data, bytes_read); + MessageLoop::current()->Quit(); + } + + void DidWrite(PlatformFileError error, + int bytes_written) { + error_ = error; + bytes_written_ = bytes_written; + MessageLoop::current()->Quit(); + } + + protected: + PlatformFile GetTestPlatformFile(int flags) { + if (file_ != kInvalidPlatformFileValue) + return file_; + bool created; + PlatformFileError error; + file_ = CreatePlatformFile(test_path(), flags, &created, &error); + EXPECT_EQ(PLATFORM_FILE_OK, error); + EXPECT_NE(kInvalidPlatformFileValue, file_); + return file_; + } + + TaskRunner* file_task_runner() const { + return file_thread_.message_loop_proxy().get(); + } + const FilePath& test_dir_path() const { return dir_.path(); } + const FilePath test_path() const { return dir_.path().AppendASCII("test"); } + + MessageLoop message_loop_; + Thread file_thread_; + + ScopedTempDir dir_; + PlatformFileError error_; + bool created_; + PlatformFile file_; + FilePath path_; + PlatformFileInfo file_info_; + std::vector<char> buffer_; + int bytes_written_; + WeakPtrFactory<FileUtilProxyTest> weak_factory_; +}; + +TEST_F(FileUtilProxyTest, CreateOrOpen_Create) { + FileUtilProxy::CreateOrOpen( + file_task_runner(), + test_path(), + PLATFORM_FILE_CREATE | PLATFORM_FILE_READ, + Bind(&FileUtilProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + + EXPECT_EQ(PLATFORM_FILE_OK, error_); + EXPECT_TRUE(created_); + EXPECT_NE(kInvalidPlatformFileValue, file_); + EXPECT_TRUE(file_util::PathExists(test_path())); +} + +TEST_F(FileUtilProxyTest, CreateOrOpen_Open) { + // Creates a file. + file_util::WriteFile(test_path(), NULL, 0); + ASSERT_TRUE(file_util::PathExists(test_path())); + + // Opens the created file. + FileUtilProxy::CreateOrOpen( + file_task_runner(), + test_path(), + PLATFORM_FILE_OPEN | PLATFORM_FILE_READ, + Bind(&FileUtilProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + + EXPECT_EQ(PLATFORM_FILE_OK, error_); + EXPECT_FALSE(created_); + EXPECT_NE(kInvalidPlatformFileValue, file_); +} + +TEST_F(FileUtilProxyTest, CreateOrOpen_OpenNonExistent) { + FileUtilProxy::CreateOrOpen( + file_task_runner(), + test_path(), + PLATFORM_FILE_OPEN | PLATFORM_FILE_READ, + Bind(&FileUtilProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + EXPECT_EQ(PLATFORM_FILE_ERROR_NOT_FOUND, error_); + EXPECT_FALSE(created_); + EXPECT_EQ(kInvalidPlatformFileValue, file_); + EXPECT_FALSE(file_util::PathExists(test_path())); +} + +TEST_F(FileUtilProxyTest, Close) { + // Creates a file. + PlatformFile file = GetTestPlatformFile( + PLATFORM_FILE_CREATE | PLATFORM_FILE_WRITE); + +#if defined(OS_WIN) + // This fails on Windows if the file is not closed. + EXPECT_FALSE(file_util::Move(test_path(), + test_dir_path().AppendASCII("new"))); +#endif + + FileUtilProxy::Close( + file_task_runner(), + file, + Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + EXPECT_EQ(PLATFORM_FILE_OK, error_); + + // Now it should pass on all platforms. + EXPECT_TRUE(file_util::Move(test_path(), test_dir_path().AppendASCII("new"))); +} + +TEST_F(FileUtilProxyTest, CreateTemporary) { + FileUtilProxy::CreateTemporary( + file_task_runner(), 0 /* additional_file_flags */, + Bind(&FileUtilProxyTest::DidCreateTemporary, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + EXPECT_EQ(PLATFORM_FILE_OK, error_); + EXPECT_TRUE(file_util::PathExists(path_)); + EXPECT_NE(kInvalidPlatformFileValue, file_); + + // The file should be writable. +#if defined(OS_WIN) + HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + OVERLAPPED overlapped = {0}; + overlapped.hEvent = hEvent; + DWORD bytes_written; + if (!::WriteFile(file_, "test", 4, &bytes_written, &overlapped)) { + // Temporary file is created with ASYNC flag, so WriteFile may return 0 + // with ERROR_IO_PENDING. + EXPECT_EQ(ERROR_IO_PENDING, GetLastError()); + GetOverlappedResult(file_, &overlapped, &bytes_written, TRUE); + } + EXPECT_EQ(4, bytes_written); +#else + // On POSIX ASYNC flag does not affect synchronous read/write behavior. + EXPECT_EQ(4, WritePlatformFile(file_, 0, "test", 4)); +#endif + EXPECT_TRUE(ClosePlatformFile(file_)); + file_ = kInvalidPlatformFileValue; + + // Make sure the written data can be read from the returned path. + std::string data; + EXPECT_TRUE(file_util::ReadFileToString(path_, &data)); + EXPECT_EQ("test", data); +} + +TEST_F(FileUtilProxyTest, GetFileInfo_File) { + // Setup. + ASSERT_EQ(4, file_util::WriteFile(test_path(), "test", 4)); + PlatformFileInfo expected_info; + file_util::GetFileInfo(test_path(), &expected_info); + + // Run. + FileUtilProxy::GetFileInfo( + file_task_runner(), + test_path(), + Bind(&FileUtilProxyTest::DidGetFileInfo, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + + // Verify. + EXPECT_EQ(PLATFORM_FILE_OK, error_); + EXPECT_EQ(expected_info.size, file_info_.size); + EXPECT_EQ(expected_info.is_directory, file_info_.is_directory); + EXPECT_EQ(expected_info.is_symbolic_link, file_info_.is_symbolic_link); + EXPECT_EQ(expected_info.last_modified, file_info_.last_modified); + EXPECT_EQ(expected_info.last_accessed, file_info_.last_accessed); + EXPECT_EQ(expected_info.creation_time, file_info_.creation_time); +} + +TEST_F(FileUtilProxyTest, GetFileInfo_Directory) { + // Setup. + ASSERT_TRUE(file_util::CreateDirectory(test_path())); + PlatformFileInfo expected_info; + file_util::GetFileInfo(test_path(), &expected_info); + + // Run. + FileUtilProxy::GetFileInfo( + file_task_runner(), + test_path(), + Bind(&FileUtilProxyTest::DidGetFileInfo, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + + // Verify. + EXPECT_EQ(PLATFORM_FILE_OK, error_); + EXPECT_EQ(expected_info.size, file_info_.size); + EXPECT_EQ(expected_info.is_directory, file_info_.is_directory); + EXPECT_EQ(expected_info.is_symbolic_link, file_info_.is_symbolic_link); + EXPECT_EQ(expected_info.last_modified, file_info_.last_modified); + EXPECT_EQ(expected_info.last_accessed, file_info_.last_accessed); + EXPECT_EQ(expected_info.creation_time, file_info_.creation_time); +} + +TEST_F(FileUtilProxyTest, Read) { + // Setup. + const char expected_data[] = "bleh"; + int expected_bytes = arraysize(expected_data); + ASSERT_EQ(expected_bytes, + file_util::WriteFile(test_path(), expected_data, expected_bytes)); + + // Run. + FileUtilProxy::Read( + file_task_runner(), + GetTestPlatformFile(PLATFORM_FILE_OPEN | PLATFORM_FILE_READ), + 0, // offset + 128, + Bind(&FileUtilProxyTest::DidRead, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + + // Verify. + EXPECT_EQ(PLATFORM_FILE_OK, error_); + EXPECT_EQ(expected_bytes, static_cast<int>(buffer_.size())); + for (size_t i = 0; i < buffer_.size(); ++i) { + EXPECT_EQ(expected_data[i], buffer_[i]); + } +} + +TEST_F(FileUtilProxyTest, WriteAndFlush) { + const char data[] = "foo!"; + int data_bytes = ARRAYSIZE_UNSAFE(data); + PlatformFile file = GetTestPlatformFile( + PLATFORM_FILE_CREATE | PLATFORM_FILE_WRITE); + + FileUtilProxy::Write( + file_task_runner(), + file, + 0, // offset + data, + data_bytes, + Bind(&FileUtilProxyTest::DidWrite, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + EXPECT_EQ(PLATFORM_FILE_OK, error_); + EXPECT_EQ(data_bytes, bytes_written_); + + // Flush the written data. (So that the following read should always + // succeed. On some platforms it may work with or without this flush.) + FileUtilProxy::Flush( + file_task_runner(), + file, + Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + EXPECT_EQ(PLATFORM_FILE_OK, error_); + + // Verify the written data. + char buffer[10]; + EXPECT_EQ(data_bytes, file_util::ReadFile(test_path(), buffer, data_bytes)); + for (int i = 0; i < data_bytes; ++i) { + EXPECT_EQ(data[i], buffer[i]); + } +} + +TEST_F(FileUtilProxyTest, Touch) { + Time last_accessed_time = Time::Now() - TimeDelta::FromDays(12345); + Time last_modified_time = Time::Now() - TimeDelta::FromHours(98765); + + FileUtilProxy::Touch( + file_task_runner(), + GetTestPlatformFile(PLATFORM_FILE_CREATE | + PLATFORM_FILE_WRITE | + PLATFORM_FILE_WRITE_ATTRIBUTES), + last_accessed_time, + last_modified_time, + Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + EXPECT_EQ(PLATFORM_FILE_OK, error_); + + PlatformFileInfo info; + file_util::GetFileInfo(test_path(), &info); + + // The returned values may only have the seconds precision, so we cast + // the double values to int here. + EXPECT_EQ(static_cast<int>(last_modified_time.ToDoubleT()), + static_cast<int>(info.last_modified.ToDoubleT())); + EXPECT_EQ(static_cast<int>(last_accessed_time.ToDoubleT()), + static_cast<int>(info.last_accessed.ToDoubleT())); +} + +TEST_F(FileUtilProxyTest, Truncate_Shrink) { + // Setup. + const char kTestData[] = "0123456789"; + ASSERT_EQ(10, file_util::WriteFile(test_path(), kTestData, 10)); + PlatformFileInfo info; + file_util::GetFileInfo(test_path(), &info); + ASSERT_EQ(10, info.size); + + // Run. + FileUtilProxy::Truncate( + file_task_runner(), + GetTestPlatformFile(PLATFORM_FILE_OPEN | PLATFORM_FILE_WRITE), + 7, + Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + + // Verify. + file_util::GetFileInfo(test_path(), &info); + ASSERT_EQ(7, info.size); + + char buffer[7]; + EXPECT_EQ(7, file_util::ReadFile(test_path(), buffer, 7)); + int i = 0; + for (; i < 7; ++i) + EXPECT_EQ(kTestData[i], buffer[i]); +} + +TEST_F(FileUtilProxyTest, Truncate_Expand) { + // Setup. + const char kTestData[] = "9876543210"; + ASSERT_EQ(10, file_util::WriteFile(test_path(), kTestData, 10)); + PlatformFileInfo info; + file_util::GetFileInfo(test_path(), &info); + ASSERT_EQ(10, info.size); + + // Run. + FileUtilProxy::Truncate( + file_task_runner(), + GetTestPlatformFile(PLATFORM_FILE_OPEN | PLATFORM_FILE_WRITE), + 53, + Bind(&FileUtilProxyTest::DidFinish, weak_factory_.GetWeakPtr())); + MessageLoop::current()->Run(); + + // Verify. + file_util::GetFileInfo(test_path(), &info); + ASSERT_EQ(53, info.size); + + char buffer[53]; + EXPECT_EQ(53, file_util::ReadFile(test_path(), buffer, 53)); + int i = 0; + for (; i < 10; ++i) + EXPECT_EQ(kTestData[i], buffer[i]); + for (; i < 53; ++i) + EXPECT_EQ(0, buffer[i]); +} + +} // namespace base |