blob: becfcdc5329097ece4bf51388d450b5c43198bd3 [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 "chrome/browser/chromeos/drive/drive_scheduler.h"
#include "base/bind.h"
#include "base/file_util.h"
#include "base/json/json_reader.h"
#include "base/prefs/pref_service.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/chromeos/drive/drive_test_util.h"
#include "chrome/browser/google_apis/drive_api_parser.h"
#include "chrome/browser/google_apis/fake_drive_service.h"
#include "chrome/browser/google_apis/gdata_wapi_parser.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::AnyNumber;
using ::testing::DoAll;
using ::testing::Eq;
using ::testing::Return;
using ::testing::StrictMock;
using ::testing::_;
namespace drive {
namespace {
class MockNetworkChangeNotifier : public net::NetworkChangeNotifier {
public:
MOCK_CONST_METHOD0(GetCurrentConnectionType,
net::NetworkChangeNotifier::ConnectionType());
};
class FakeDriveUploader : public google_apis::DriveUploaderInterface {
public:
FakeDriveUploader() {}
virtual ~FakeDriveUploader() {}
// DriveUploaderInterface overrides.
virtual void UploadNewFile(
const GURL& upload_location,
const base::FilePath& drive_file_path,
const base::FilePath& local_file_path,
const std::string& title,
const std::string& content_type,
const google_apis::UploadCompletionCallback& callback) OVERRIDE {
}
virtual void UploadExistingFile(
const GURL& upload_location,
const base::FilePath& drive_file_path,
const base::FilePath& local_file_path,
const std::string& content_type,
const std::string& etag,
const google_apis::UploadCompletionCallback& callback) OVERRIDE {
}
};
void CopyResourceIdFromGetResourceEntryCallback(
std::vector<std::string>* id_list_out,
const std::string& requested_id,
google_apis::GDataErrorCode error_in,
scoped_ptr<google_apis::ResourceEntry> resource_entry_in) {
id_list_out->push_back(requested_id);
}
} // namespace
class DriveSchedulerTest : public testing::Test {
public:
DriveSchedulerTest()
: ui_thread_(content::BrowserThread::UI, &message_loop_),
profile_(new TestingProfile) {
}
virtual void SetUp() OVERRIDE {
mock_network_change_notifier_.reset(new MockNetworkChangeNotifier);
fake_drive_service_.reset(new google_apis::FakeDriveService());
fake_drive_service_->LoadResourceListForWapi(
"gdata/root_feed.json");
fake_drive_service_->LoadAccountMetadataForWapi(
"gdata/account_metadata.json");
fake_drive_service_->LoadAppListForDriveApi(
"drive/applist.json");
fake_uploader_.reset(new FakeDriveUploader);
scheduler_.reset(new DriveScheduler(profile_.get(),
fake_drive_service_.get(),
fake_uploader_.get()));
scheduler_->Initialize();
scheduler_->SetDisableThrottling(true);
}
virtual void TearDown() OVERRIDE {
// The scheduler should be deleted before NetworkLibrary, as it
// registers itself as observer of NetworkLibrary.
scheduler_.reset();
google_apis::test_util::RunBlockingPoolTask();
fake_drive_service_.reset();
mock_network_change_notifier_.reset();
}
// Sets up MockNetworkChangeNotifier as if it's connected to a network with
// the specified connection type.
void ChangeConnectionType(net::NetworkChangeNotifier::ConnectionType type) {
EXPECT_CALL(*mock_network_change_notifier_, GetCurrentConnectionType())
.WillRepeatedly(Return(type));
// Notify the sync client that the network is changed. This is done via
// NetworkChangeNotifier in production, but here, we simulate the behavior
// by directly calling OnConnectionTypeChanged().
scheduler_->OnConnectionTypeChanged(type);
}
// Sets up MockNetworkChangeNotifier as if it's connected to wifi network.
void ConnectToWifi() {
ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
}
// Sets up MockNetworkChangeNotifier as if it's connected to cellular network.
void ConnectToCellular() {
ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_2G);
}
// Sets up MockNetworkChangeNotifier as if it's connected to wimax network.
void ConnectToWimax() {
ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_4G);
}
// Sets up MockNetworkChangeNotifier as if it's disconnected.
void ConnectToNone() {
ChangeConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
}
protected:
MessageLoopForUI message_loop_;
content::TestBrowserThread ui_thread_;
scoped_ptr<TestingProfile> profile_;
scoped_ptr<DriveScheduler> scheduler_;
scoped_ptr<MockNetworkChangeNotifier> mock_network_change_notifier_;
scoped_ptr<google_apis::FakeDriveService> fake_drive_service_;
scoped_ptr<FakeDriveUploader> fake_uploader_;
};
TEST_F(DriveSchedulerTest, GetAppList) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::AppList> app_list;
scheduler_->GetAppList(
base::Bind(
&google_apis::test_util::CopyResultsFromGetAppListCallback,
&error,
&app_list));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
ASSERT_TRUE(app_list);
}
TEST_F(DriveSchedulerTest, GetAccountMetadata) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::AccountMetadataFeed> account_metadata;
scheduler_->GetAccountMetadata(
base::Bind(
&google_apis::test_util::CopyResultsFromGetAccountMetadataCallback,
&error,
&account_metadata));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
ASSERT_TRUE(account_metadata);
}
TEST_F(DriveSchedulerTest, GetResourceList) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::ResourceList> resource_list;
scheduler_->GetResourceList(
GURL("http://example.com/gdata/root_feed.json"),
0,
std::string(),
true,
std::string(),
base::Bind(
&google_apis::test_util::CopyResultsFromGetResourceListCallback,
&error,
&resource_list));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
ASSERT_TRUE(resource_list);
}
TEST_F(DriveSchedulerTest, GetResourceEntry) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::ResourceEntry> entry;
scheduler_->GetResourceEntry(
"file:2_file_resource_id", // resource ID
DriveClientContext(USER_INITIATED),
base::Bind(
&google_apis::test_util::CopyResultsFromGetResourceEntryCallback,
&error,
&entry));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
ASSERT_TRUE(entry);
}
TEST_F(DriveSchedulerTest, DeleteResource) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scheduler_->DeleteResource(
"file:2_file_resource_id",
base::Bind(
&google_apis::test_util::CopyResultsFromEntryActionCallback,
&error));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
}
TEST_F(DriveSchedulerTest, CopyHostedDocument) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::ResourceEntry> entry;
scheduler_->CopyHostedDocument(
"document:5_document_resource_id", // resource ID
"New Document", // new name
base::Bind(
&google_apis::test_util::CopyResultsFromGetResourceEntryCallback,
&error,
&entry));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
ASSERT_TRUE(entry);
}
TEST_F(DriveSchedulerTest, RenameResource) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scheduler_->RenameResource(
"file:2_file_resource_id",
"New Name",
base::Bind(
&google_apis::test_util::CopyResultsFromEntryActionCallback,
&error));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
}
TEST_F(DriveSchedulerTest, AddResourceToDirectory) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scheduler_->AddResourceToDirectory(
"folder:1_folder_resource_id",
"file:2_file_resource_id",
base::Bind(
&google_apis::test_util::CopyResultsFromEntryActionCallback,
&error));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
}
TEST_F(DriveSchedulerTest, RemoveResourceFromDirectory) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scheduler_->RemoveResourceFromDirectory(
"folder:1_folder_resource_id",
"file:subdirectory_file_1_id", // resource ID
base::Bind(
&google_apis::test_util::CopyResultsFromEntryActionCallback,
&error));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_SUCCESS, error);
}
TEST_F(DriveSchedulerTest, AddNewDirectory) {
ConnectToWifi();
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::ResourceEntry> entry;
scheduler_->AddNewDirectory(
fake_drive_service_->GetRootResourceId(), // Root directory.
"New Directory",
base::Bind(
&google_apis::test_util::CopyResultsFromGetResourceEntryCallback,
&error,
&entry));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(google_apis::HTTP_CREATED, error);
ASSERT_TRUE(entry);
}
TEST_F(DriveSchedulerTest, GetResourceEntryPriority) {
ConnectToWifi();
std::string resource_1("file:1_file_resource_id");
std::string resource_2("file:2_file_resource_id");
std::string resource_3("file:3_file_resource_id");
std::string resource_4("file:4_file_resource_id");
std::vector<std::string> resource_ids;
scheduler_->GetResourceEntry(
resource_1, // resource ID
DriveClientContext(USER_INITIATED),
base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
&resource_ids,
resource_1));
scheduler_->GetResourceEntry(
resource_2, // resource ID
DriveClientContext(USER_INITIATED),
base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
&resource_ids,
resource_2));
scheduler_->GetResourceEntry(
resource_3, // resource ID
DriveClientContext(BACKGROUND),
base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
&resource_ids,
resource_3));
scheduler_->GetResourceEntry(
resource_4, // resource ID
DriveClientContext(USER_INITIATED),
base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
&resource_ids,
resource_4));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(resource_ids.size(), 4ul);
ASSERT_EQ(resource_ids[0], resource_1);
ASSERT_EQ(resource_ids[1], resource_2);
ASSERT_EQ(resource_ids[2], resource_4);
ASSERT_EQ(resource_ids[3], resource_3);
}
TEST_F(DriveSchedulerTest, GetResourceEntryNoConnection) {
ConnectToNone();
std::string resource("file:1_file_resource_id");
std::vector<std::string> resource_ids;
scheduler_->GetResourceEntry(
resource, // resource ID
DriveClientContext(BACKGROUND),
base::Bind(&CopyResourceIdFromGetResourceEntryCallback,
&resource_ids,
resource));
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(resource_ids.size(), 0ul);
// Reconnect to the net.
ConnectToWifi();
google_apis::test_util::RunBlockingPoolTask();
ASSERT_EQ(resource_ids.size(), 1ul);
ASSERT_EQ(resource_ids[0], resource);
}
TEST_F(DriveSchedulerTest, DownloadFileCellularDisabled) {
ConnectToCellular();
// Disable fetching over cellular network.
profile_->GetPrefs()->SetBoolean(prefs::kDisableDriveOverCellular, true);
// Try to get a file in the background
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
const GURL kContentUrl("https://file_content_url/");
const base::FilePath kOutputFilePath =
temp_dir.path().AppendASCII("whatever.txt");
google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
base::FilePath output_file_path;
scheduler_->DownloadFile(
base::FilePath::FromUTF8Unsafe("/drive/whatever.txt"), // virtual path
kOutputFilePath,
kContentUrl,
DriveClientContext(BACKGROUND),
base::Bind(&google_apis::test_util::CopyResultsFromDownloadActionCallback,
&download_error,
&output_file_path),
google_apis::GetContentCallback());
// Metadata should still work
google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::AccountMetadataFeed> account_metadata;
// Try to get the metadata
scheduler_->GetAccountMetadata(
base::Bind(
&google_apis::test_util::CopyResultsFromGetAccountMetadataCallback,
&metadata_error,
&account_metadata));
google_apis::test_util::RunBlockingPoolTask();
// Check the metadata
ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
ASSERT_TRUE(account_metadata);
// Check the download
EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
// Switch to a Wifi connection
ConnectToWifi();
google_apis::test_util::RunBlockingPoolTask();
// Check the download again
EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
std::string content;
EXPECT_EQ(output_file_path, kOutputFilePath);
ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content));
// The content is "x"s of the file size specified in root_feed.json.
EXPECT_EQ("xxxxxxxxxx", content);
}
TEST_F(DriveSchedulerTest, DownloadFileWimaxDisabled) {
ConnectToWimax();
// Disable fetching over cellular network.
profile_->GetPrefs()->SetBoolean(prefs::kDisableDriveOverCellular, true);
// Try to get a file in the background
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
const GURL kContentUrl("https://file_content_url/");
const base::FilePath kOutputFilePath =
temp_dir.path().AppendASCII("whatever.txt");
google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
base::FilePath output_file_path;
scheduler_->DownloadFile(
base::FilePath::FromUTF8Unsafe("/drive/whatever.txt"), // virtual path
kOutputFilePath,
kContentUrl,
DriveClientContext(BACKGROUND),
base::Bind(&google_apis::test_util::CopyResultsFromDownloadActionCallback,
&download_error,
&output_file_path),
google_apis::GetContentCallback());
// Metadata should still work
google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::AccountMetadataFeed> account_metadata;
// Try to get the metadata
scheduler_->GetAccountMetadata(
base::Bind(
&google_apis::test_util::CopyResultsFromGetAccountMetadataCallback,
&metadata_error,
&account_metadata));
google_apis::test_util::RunBlockingPoolTask();
// Check the metadata
ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
ASSERT_TRUE(account_metadata);
// Check the download
EXPECT_EQ(google_apis::GDATA_OTHER_ERROR, download_error);
// Switch to a Wifi connection
ConnectToWifi();
google_apis::test_util::RunBlockingPoolTask();
// Check the download again
EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
std::string content;
EXPECT_EQ(output_file_path, kOutputFilePath);
ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content));
// The content is "x"s of the file size specified in root_feed.json.
EXPECT_EQ("xxxxxxxxxx", content);
}
TEST_F(DriveSchedulerTest, DownloadFileCellularEnabled) {
ConnectToCellular();
// Enable fetching over cellular network.
profile_->GetPrefs()->SetBoolean(prefs::kDisableDriveOverCellular, false);
// Try to get a file in the background
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
const GURL kContentUrl("https://file_content_url/");
const base::FilePath kOutputFilePath =
temp_dir.path().AppendASCII("whatever.txt");
google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
base::FilePath output_file_path;
scheduler_->DownloadFile(
base::FilePath::FromUTF8Unsafe("/drive/whatever.txt"), // virtual path
kOutputFilePath,
kContentUrl,
DriveClientContext(BACKGROUND),
base::Bind(&google_apis::test_util::CopyResultsFromDownloadActionCallback,
&download_error,
&output_file_path),
google_apis::GetContentCallback());
// Metadata should still work
google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::AccountMetadataFeed> account_metadata;
// Try to get the metadata
scheduler_->GetAccountMetadata(
base::Bind(
&google_apis::test_util::CopyResultsFromGetAccountMetadataCallback,
&metadata_error,
&account_metadata));
google_apis::test_util::RunBlockingPoolTask();
// Check the metadata
ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
ASSERT_TRUE(account_metadata);
// Check the download
EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
std::string content;
EXPECT_EQ(output_file_path, kOutputFilePath);
ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content));
// The content is "x"s of the file size specified in root_feed.json.
EXPECT_EQ("xxxxxxxxxx", content);
}
TEST_F(DriveSchedulerTest, DownloadFileWimaxEnabled) {
ConnectToWimax();
// Enable fetching over cellular network.
profile_->GetPrefs()->SetBoolean(prefs::kDisableDriveOverCellular, false);
// Try to get a file in the background
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
const GURL kContentUrl("https://file_content_url/");
const base::FilePath kOutputFilePath =
temp_dir.path().AppendASCII("whatever.txt");
google_apis::GDataErrorCode download_error = google_apis::GDATA_OTHER_ERROR;
base::FilePath output_file_path;
scheduler_->DownloadFile(
base::FilePath::FromUTF8Unsafe("/drive/whatever.txt"), // virtual path
kOutputFilePath,
kContentUrl,
DriveClientContext(BACKGROUND),
base::Bind(&google_apis::test_util::CopyResultsFromDownloadActionCallback,
&download_error,
&output_file_path),
google_apis::GetContentCallback());
// Metadata should still work
google_apis::GDataErrorCode metadata_error = google_apis::GDATA_OTHER_ERROR;
scoped_ptr<google_apis::AccountMetadataFeed> account_metadata;
// Try to get the metadata
scheduler_->GetAccountMetadata(
base::Bind(
&google_apis::test_util::CopyResultsFromGetAccountMetadataCallback,
&metadata_error,
&account_metadata));
google_apis::test_util::RunBlockingPoolTask();
// Check the metadata
ASSERT_EQ(google_apis::HTTP_SUCCESS, metadata_error);
ASSERT_TRUE(account_metadata);
// Check the download
EXPECT_EQ(google_apis::HTTP_SUCCESS, download_error);
std::string content;
EXPECT_EQ(output_file_path, kOutputFilePath);
ASSERT_TRUE(file_util::ReadFileToString(output_file_path, &content));
// The content is "x"s of the file size specified in root_feed.json.
EXPECT_EQ("xxxxxxxxxx", content);
}
} // namespace drive