blob: cb9cf4479455b64f9c3891759c39cd689e903126 [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 <string>
#include <vector>
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
#include "chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.h"
#include "chrome/browser/chromeos/file_system_provider/service.h"
#include "chrome/browser/chromeos/file_system_provider/service_factory.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_file_system_context.h"
#include "extensions/browser/extension_registry.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/browser/fileapi/async_file_util.h"
#include "webkit/browser/fileapi/external_mount_points.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_url.h"
#include "webkit/common/blob/shareable_file_reference.h"
namespace chromeos {
namespace file_system_provider {
namespace {
const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
const char kFileSystemId[] = "testing-file-system";
// Logs callbacks invocations on the tested operations.
// TODO(mtomasz): Store and verify more arguments, once the operations return
// anything else than just an error.
class EventLogger {
public:
EventLogger() : weak_ptr_factory_(this) {}
virtual ~EventLogger() {}
void OnStatus(base::File::Error error) {
error_.reset(new base::File::Error(error));
}
void OnCreateOrOpen(base::File file,
const base::Closure& on_close_callback) {
if (file.IsValid())
error_.reset(new base::File::Error(base::File::FILE_OK));
error_.reset(new base::File::Error(file.error_details()));
}
void OnEnsureFileExists(base::File::Error error, bool created) {
error_.reset(new base::File::Error(error));
}
void OnGetFileInfo(base::File::Error error,
const base::File::Info& file_info) {
error_.reset(new base::File::Error(error));
}
void OnReadDirectory(base::File::Error error,
const fileapi::AsyncFileUtil::EntryList& file_list,
bool has_more) {
error_.reset(new base::File::Error(error));
}
void OnCreateSnapshotFile(
base::File::Error error,
const base::File::Info& file_info,
const base::FilePath& platform_path,
const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
error_.reset(new base::File::Error(error));
}
void OnCopyFileProgress(int64 size) {}
base::WeakPtr<EventLogger> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
base::File::Error* error() { return error_.get(); }
private:
scoped_ptr<base::File::Error> error_;
base::WeakPtrFactory<EventLogger> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(EventLogger);
};
// Creates a cracked FileSystemURL for tests.
fileapi::FileSystemURL CreateFileSystemURL(const std::string& mount_point_name,
const base::FilePath& file_path) {
const std::string origin = std::string("chrome-extension://") + kExtensionId;
const fileapi::ExternalMountPoints* const mount_points =
fileapi::ExternalMountPoints::GetSystemInstance();
return mount_points->CreateCrackedFileSystemURL(
GURL(origin),
fileapi::kFileSystemTypeExternal,
base::FilePath::FromUTF8Unsafe(mount_point_name).Append(file_path));
}
// Creates a Service instance. Used to be able to destroy the service in
// TearDown().
KeyedService* CreateService(content::BrowserContext* context) {
return new Service(Profile::FromBrowserContext(context),
extensions::ExtensionRegistry::Get(context));
}
} // namespace
// Tests in this file are very lightweight and just test integration between
// AsyncFileUtil and ProvideFileSystemInterface. Currently it tests if not
// implemented operations return a correct error code. For not allowed
// operations it is FILE_ERROR_ACCESS_DENIED, and for not implemented the error
// is FILE_ERROR_INVALID_OPERATION.
class FileSystemProviderProviderAsyncFileUtilTest : public testing::Test {
protected:
FileSystemProviderProviderAsyncFileUtilTest() {}
virtual ~FileSystemProviderProviderAsyncFileUtilTest() {}
virtual void SetUp() OVERRIDE {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
profile_manager_.reset(
new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
ASSERT_TRUE(profile_manager_->SetUp());
profile_ = profile_manager_->CreateTestingProfile("testing-profile");
async_file_util_.reset(new internal::ProviderAsyncFileUtil);
file_system_context_ =
content::CreateFileSystemContextForTesting(NULL, data_dir_.path());
ServiceFactory::GetInstance()->SetTestingFactory(profile_, &CreateService);
Service* service = Service::Get(profile_); // Owned by its factory.
service->SetFileSystemFactoryForTests(
base::Bind(&FakeProvidedFileSystem::Create));
const bool result = service->MountFileSystem(
kExtensionId, kFileSystemId, "Testing File System");
ASSERT_TRUE(result);
const ProvidedFileSystemInfo& file_system_info =
service->GetProvidedFileSystem(kExtensionId, kFileSystemId)
->GetFileSystemInfo();
const std::string mount_point_name =
file_system_info.mount_path().BaseName().AsUTF8Unsafe();
file_url_ = CreateFileSystemURL(
mount_point_name, base::FilePath::FromUTF8Unsafe("hello/world.txt"));
ASSERT_TRUE(file_url_.is_valid());
directory_url_ = CreateFileSystemURL(
mount_point_name, base::FilePath::FromUTF8Unsafe("hello"));
ASSERT_TRUE(directory_url_.is_valid());
root_url_ = CreateFileSystemURL(mount_point_name, base::FilePath());
ASSERT_TRUE(root_url_.is_valid());
}
virtual void TearDown() OVERRIDE {
// Setting the testing factory to NULL will destroy the created service
// associated with the testing profile.
ServiceFactory::GetInstance()->SetTestingFactory(profile_, NULL);
}
scoped_ptr<fileapi::FileSystemOperationContext> CreateOperationContext() {
return make_scoped_ptr(
new fileapi::FileSystemOperationContext(file_system_context_.get()));
}
content::TestBrowserThreadBundle thread_bundle_;
base::ScopedTempDir data_dir_;
scoped_ptr<TestingProfileManager> profile_manager_;
TestingProfile* profile_; // Owned by TestingProfileManager.
scoped_ptr<fileapi::AsyncFileUtil> async_file_util_;
scoped_refptr<fileapi::FileSystemContext> file_system_context_;
fileapi::FileSystemURL file_url_;
fileapi::FileSystemURL directory_url_;
fileapi::FileSystemURL root_url_;
};
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, CreateOrOpen_Create) {
EventLogger logger;
async_file_util_->CreateOrOpen(
CreateOperationContext(),
file_url_,
base::File::FLAG_CREATE,
base::Bind(&EventLogger::OnCreateOrOpen, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, CreateOrOpen_CreateAlways) {
EventLogger logger;
async_file_util_->CreateOrOpen(
CreateOperationContext(),
file_url_,
base::File::FLAG_CREATE_ALWAYS,
base::Bind(&EventLogger::OnCreateOrOpen, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, CreateOrOpen_OpenAlways) {
EventLogger logger;
async_file_util_->CreateOrOpen(
CreateOperationContext(),
file_url_,
base::File::FLAG_OPEN_ALWAYS,
base::Bind(&EventLogger::OnCreateOrOpen, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest,
CreateOrOpen_OpenTruncated) {
EventLogger logger;
async_file_util_->CreateOrOpen(
CreateOperationContext(),
file_url_,
base::File::FLAG_OPEN_TRUNCATED,
base::Bind(&EventLogger::OnCreateOrOpen, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, CreateOrOpen_Open) {
EventLogger logger;
async_file_util_->CreateOrOpen(
CreateOperationContext(),
file_url_,
base::File::FLAG_OPEN,
base::Bind(&EventLogger::OnCreateOrOpen, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, EnsureFileExists) {
EventLogger logger;
async_file_util_->EnsureFileExists(
CreateOperationContext(),
file_url_,
base::Bind(&EventLogger::OnEnsureFileExists, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, CreateDirectory) {
EventLogger logger;
async_file_util_->CreateDirectory(
CreateOperationContext(),
directory_url_,
false, // exclusive
false, // recursive
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, GetFileInfo) {
EventLogger logger;
async_file_util_->GetFileInfo(
CreateOperationContext(),
root_url_,
base::Bind(&EventLogger::OnGetFileInfo, logger.GetWeakPtr()));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_OK, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, ReadDirectory) {
EventLogger logger;
async_file_util_->ReadDirectory(
CreateOperationContext(),
root_url_,
base::Bind(&EventLogger::OnReadDirectory, logger.GetWeakPtr()));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_OK, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, Touch) {
EventLogger logger;
async_file_util_->CreateDirectory(
CreateOperationContext(),
file_url_,
false, // exclusive
false, // recursive
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, Truncate) {
EventLogger logger;
async_file_util_->Truncate(
CreateOperationContext(),
file_url_,
0, // length
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, CopyFileLocal) {
EventLogger logger;
async_file_util_->CopyFileLocal(
CreateOperationContext(),
file_url_, // src_url
file_url_, // dst_url
fileapi::FileSystemOperation::OPTION_NONE,
base::Bind(&EventLogger::OnCopyFileProgress, logger.GetWeakPtr()),
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, MoveFileLocal) {
EventLogger logger;
async_file_util_->MoveFileLocal(
CreateOperationContext(),
file_url_, // src_url
file_url_, // dst_url
fileapi::FileSystemOperation::OPTION_NONE,
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, CopyInForeignFile) {
EventLogger logger;
async_file_util_->CopyInForeignFile(
CreateOperationContext(),
base::FilePath(), // src_file_path
file_url_, // dst_url
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, DeleteFile) {
EventLogger logger;
async_file_util_->DeleteFile(
CreateOperationContext(),
file_url_,
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, DeleteDirectory) {
EventLogger logger;
async_file_util_->DeleteDirectory(
CreateOperationContext(),
directory_url_,
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, DeleteRecursively) {
EventLogger logger;
async_file_util_->DeleteRecursively(
CreateOperationContext(),
directory_url_,
base::Bind(&EventLogger::OnStatus, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_ACCESS_DENIED, *logger.error());
}
TEST_F(FileSystemProviderProviderAsyncFileUtilTest, CreateSnapshotFile) {
EventLogger logger;
async_file_util_->CreateSnapshotFile(
CreateOperationContext(),
file_url_,
base::Bind(&EventLogger::OnCreateSnapshotFile, logger.GetWeakPtr()));
ASSERT_TRUE(logger.error());
EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, *logger.error());
}
} // namespace file_system_provider
} // namespace chromeos