blob: 4caccde0538ccf0bbd750b105419b151450a7995 [file] [log] [blame]
// Copyright 2014 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 "chrome/browser/chromeos/drive/fileapi/fileapi_worker.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/chromeos/drive/dummy_file_system.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "google_apis/drive/test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace drive {
namespace fileapi_internal {
namespace {
// Increments |num_called| for checking how many times the closure is called.
void Increment(int* num_called) {
++*num_called;
}
// Returns the |instance| as is.
FileSystemInterface* GetFileSystem(FileSystemInterface* instance) {
return instance;
}
// A test file system that always returns |local_file_path|. For testing
// purpose, it checks if |open_mode| is the expected value, and record if the
// close callback is called.
class TestFileSystemForOpenFile : public DummyFileSystem {
public:
TestFileSystemForOpenFile(const base::FilePath& local_file_path,
OpenMode expected_open_mode)
: local_file_path_(local_file_path),
expected_open_mode_(expected_open_mode),
closed_(false) {
}
void OpenFile(const base::FilePath& file_path,
OpenMode open_mode,
const std::string& mime_type,
const drive::OpenFileCallback& callback) override {
EXPECT_EQ(expected_open_mode_, open_mode);
callback.Run(
FILE_ERROR_OK,
local_file_path_,
base::Bind(&TestFileSystemForOpenFile::Close, base::Unretained(this)));
}
void Close() {
closed_ = true;
}
bool closed() const { return closed_; }
private:
const base::FilePath local_file_path_;
const OpenMode expected_open_mode_;
bool closed_;
};
// Helper function of testing OpenFile() for write access. It checks that the
// file handle correctly writes to the expected file.
void VerifyWrite(
int64 expected_size,
const base::FilePath& expected_written_path,
const std::string& write_data,
base::File file,
const base::Closure& close_callback) {
// Check that the file was properly opened.
EXPECT_TRUE(file.IsValid());
EXPECT_FALSE(close_callback.is_null());
// Check that the file has the expected length (i.e., truncated or not)
base::File::Info info;
EXPECT_TRUE(file.GetInfo(&info));
EXPECT_EQ(expected_size, info.size);
// Write some data.
const int data_size = static_cast<int>(write_data.size());
EXPECT_EQ(data_size, file.Write(0, write_data.c_str(), data_size));
EXPECT_TRUE(file.SetLength(data_size));
// Close.
file.Close();
close_callback.Run();
// Checks that the written content goes to |expected_written_path|. I.e.,
// the |file| handle is pointing to the file.
std::string written;
EXPECT_TRUE(base::ReadFileToString(expected_written_path, &written));
EXPECT_EQ(write_data, written);
}
// Helper function of testing OpenFile() for read access. It checks that the
// file is readable and contains |expected_data|.
void VerifyRead(const std::string& expected_data,
base::File file,
const base::Closure& close_callback) {
// Check that the file was properly opened.
EXPECT_TRUE(file.IsValid());
EXPECT_FALSE(close_callback.is_null());
// Check that the file has the expected content.
const int data_size = static_cast<int>(expected_data.size());
base::File::Info info;
EXPECT_TRUE(file.GetInfo(&info));
EXPECT_EQ(data_size, info.size);
std::vector<char> buffer(data_size);
EXPECT_EQ(data_size, file.Read(0, buffer.data(), data_size));
EXPECT_EQ(expected_data, std::string(buffer.begin(), buffer.end()));
// Close.
file.Close();
close_callback.Run();
}
} // namespace
class FileApiWorkerTest : public testing::Test {
private:
content::TestBrowserThreadBundle thread_bundle_;
};
TEST_F(FileApiWorkerTest, RunFileSystemCallbackSuccess) {
DummyFileSystem dummy_file_system;
FileSystemInterface* file_system = NULL;
RunFileSystemCallback(
base::Bind(&GetFileSystem, &dummy_file_system),
google_apis::test_util::CreateCopyResultCallback(&file_system),
base::Closure());
EXPECT_EQ(&dummy_file_system, file_system);
}
TEST_F(FileApiWorkerTest, RunFileSystemCallbackFail) {
FileSystemInterface* file_system = NULL;
// Make sure on_error_callback is called if file_system_getter returns NULL.
int num_called = 0;
RunFileSystemCallback(
base::Bind(&GetFileSystem, static_cast<FileSystemInterface*>(NULL)),
google_apis::test_util::CreateCopyResultCallback(&file_system),
base::Bind(&Increment, &num_called));
EXPECT_EQ(1, num_called);
// Just make sure this null |on_error_callback| doesn't cause a crash.
RunFileSystemCallback(
base::Bind(&GetFileSystem, static_cast<FileSystemInterface*>(NULL)),
google_apis::test_util::CreateCopyResultCallback(&file_system),
base::Closure());
}
TEST_F(FileApiWorkerTest, OpenFileForCreateWrite) {
const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
const std::string kWriteData = "byebye";
base::FilePath temp_path;
base::CreateTemporaryFile(&temp_path);
// CREATE => CREATE (fails if file exists.)
TestFileSystemForOpenFile file_system(temp_path, CREATE_FILE);
const int64 kExpectedSize = 0;
OpenFile(kDummyPath,
base::File::FLAG_CREATE | base::File::FLAG_WRITE,
base::Bind(&VerifyWrite, kExpectedSize, temp_path, kWriteData),
&file_system);
content::RunAllBlockingPoolTasksUntilIdle();
EXPECT_TRUE(file_system.closed());
}
TEST_F(FileApiWorkerTest, OpenFileForOpenAlwaysWrite) {
const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
const std::string kWriteData = "byebye";
const std::string kInitialData = "hello";
base::FilePath temp_path;
base::CreateTemporaryFile(&temp_path);
google_apis::test_util::WriteStringToFile(temp_path, kInitialData);
// OPEN_ALWAYS => OPEN_OR_CREATE (success whether file exists or not.)
// No truncation should take place.
TestFileSystemForOpenFile file_system(temp_path, OPEN_OR_CREATE_FILE);
const int64 kExpectedSize = static_cast<int64>(kInitialData.size());
OpenFile(kDummyPath,
base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE,
base::Bind(&VerifyWrite, kExpectedSize, temp_path, kWriteData),
&file_system);
content::RunAllBlockingPoolTasksUntilIdle();
EXPECT_TRUE(file_system.closed());
}
TEST_F(FileApiWorkerTest, OpenFileForOpenTruncatedWrite) {
const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
const std::string kInitialData = "hello";
const std::string kWriteData = "byebye";
base::FilePath temp_path;
base::CreateTemporaryFile(&temp_path);
google_apis::test_util::WriteStringToFile(temp_path, kInitialData);
// OPEN_TRUNCATED => OPEN (failure when the file did not exist.)
// It should truncate the file before passing to the callback.
TestFileSystemForOpenFile file_system(temp_path, OPEN_FILE);
const int64 kExpectedSize = 0;
OpenFile(kDummyPath,
base::File::FLAG_OPEN_TRUNCATED | base::File::FLAG_WRITE,
base::Bind(&VerifyWrite, kExpectedSize, temp_path, kWriteData),
&file_system);
content::RunAllBlockingPoolTasksUntilIdle();
EXPECT_TRUE(file_system.closed());
}
TEST_F(FileApiWorkerTest, OpenFileForOpenCreateAlwaysWrite) {
const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
const std::string kInitialData = "hello";
const std::string kWriteData = "byebye";
base::FilePath temp_path;
base::CreateTemporaryFile(&temp_path);
google_apis::test_util::WriteStringToFile(temp_path, kInitialData);
// CREATE_ALWAYS => OPEN_OR_CREATE (success whether file exists or not.)
// It should truncate the file before passing to the callback.
TestFileSystemForOpenFile file_system(temp_path, OPEN_OR_CREATE_FILE);
const int64 kExpectedSize = 0;
OpenFile(kDummyPath,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE,
base::Bind(&VerifyWrite, kExpectedSize, temp_path, kWriteData),
&file_system);
content::RunAllBlockingPoolTasksUntilIdle();
EXPECT_TRUE(file_system.closed());
}
TEST_F(FileApiWorkerTest, OpenFileForOpenRead) {
const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
const std::string kInitialData = "hello";
base::FilePath temp_path;
base::CreateTemporaryFile(&temp_path);
google_apis::test_util::WriteStringToFile(temp_path, kInitialData);
// OPEN => OPEN (failure when the file did not exist.)
TestFileSystemForOpenFile file_system(temp_path, OPEN_FILE);
OpenFile(kDummyPath,
base::File::FLAG_OPEN | base::File::FLAG_READ,
base::Bind(&VerifyRead, kInitialData),
&file_system);
content::RunAllBlockingPoolTasksUntilIdle();
EXPECT_TRUE(file_system.closed());
}
} // namespace fileapi_internal
} // namespace drive