blob: 01f4d6ea4bc344dd37ca76e6f2d86687baca4ac0 [file] [log] [blame]
// Copyright 2013 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/sync_file_system/drive_backend_v1/drive_file_sync_service.h"
#include "base/bind.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.h"
#include "chrome/browser/sync_file_system/drive_backend_v1/fake_api_util.h"
#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sync_file_system {
using drive_backend::APIUtilInterface;
using drive_backend::FakeAPIUtil;
namespace {
const char kSyncRootResourceId[] = "folder:sync_root_resource_id";
void DidInitialize(bool* done, SyncStatusCode status, bool created) {
EXPECT_EQ(SYNC_STATUS_OK, status);
*done = true;
}
void ExpectEqStatus(bool* done,
SyncStatusCode expected,
SyncStatusCode actual) {
EXPECT_FALSE(*done);
*done = true;
EXPECT_EQ(expected, actual);
}
void ExpectOkStatus(SyncStatusCode status) {
EXPECT_EQ(SYNC_STATUS_OK, status);
}
} // namespace
class DriveFileSyncServiceTest : public testing::Test {
public:
DriveFileSyncServiceTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
fake_api_util_(NULL),
metadata_store_(NULL) {}
virtual void SetUp() OVERRIDE {
RegisterSyncableFileSystem();
fake_api_util_ = new FakeAPIUtil;
ASSERT_TRUE(scoped_base_dir_.CreateUniqueTempDir());
base_dir_ = scoped_base_dir_.path();
metadata_store_ = new DriveMetadataStore(
base_dir_, base::MessageLoopProxy::current().get());
bool done = false;
metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
base::RunLoop().RunUntilIdle();
metadata_store_->SetSyncRootDirectory(kSyncRootResourceId);
EXPECT_TRUE(done);
sync_service_ = DriveFileSyncService::CreateForTesting(
&profile_,
base_dir_,
scoped_ptr<APIUtilInterface>(fake_api_util_),
scoped_ptr<DriveMetadataStore>(metadata_store_)).Pass();
base::RunLoop().RunUntilIdle();
}
virtual void TearDown() OVERRIDE {
metadata_store_ = NULL;
fake_api_util_ = NULL;
sync_service_.reset();
base::RunLoop().RunUntilIdle();
base_dir_ = base::FilePath();
RevokeSyncableFileSystem();
}
virtual ~DriveFileSyncServiceTest() {
}
protected:
FakeAPIUtil* fake_api_util() { return fake_api_util_; }
DriveMetadataStore* metadata_store() { return metadata_store_; }
DriveFileSyncService* sync_service() { return sync_service_.get(); }
std::map<GURL, std::string>* pending_batch_sync_origins() {
return &(sync_service()->pending_batch_sync_origins_);
}
// Helper function to add an origin to the given origin sync status. To make
// naming easier, each origin, resourceID, etc. will all share the same
// prefixes and only be distinguished by the given suffix ID which could be a
// number (1, 2, 3, etc.) or a letter (A, B, C, etc.).
// e.g. originA, originB, folder:resource_idA, folder:resource_idB, etc.
void AddOrigin(std::string status, const char* suffix) {
const GURL origin(std::string("chrome-extension://app_") + suffix);
const std::string resource_id(std::string("folder:resource_id") + suffix);
if (status == "Pending") {
pending_batch_sync_origins()->insert(std::make_pair(origin, resource_id));
} else if (status == "Enabled") {
metadata_store()->AddIncrementalSyncOrigin(origin, resource_id);
} else if (status == "Disabled") {
metadata_store()->AddIncrementalSyncOrigin(origin, resource_id);
metadata_store()->DisableOrigin(origin, base::Bind(&ExpectOkStatus));
} else {
NOTREACHED();
}
}
bool VerifyOriginStatusCount(size_t expected_pending,
size_t expected_enabled,
size_t expected_disabled) {
size_t actual_pending = pending_batch_sync_origins()->size();
size_t actual_enabled = metadata_store()->incremental_sync_origins().size();
size_t actual_disabled = metadata_store()->disabled_origins().size();
// Prints which counts don't match up if any.
EXPECT_EQ(expected_pending, actual_pending);
EXPECT_EQ(expected_enabled, actual_enabled);
EXPECT_EQ(expected_disabled, actual_disabled);
// If any count doesn't match, the original line number can be printed by
// simply adding ASSERT_TRUE on the call to this function.
if (expected_pending == actual_pending &&
expected_enabled == actual_enabled &&
expected_disabled == actual_disabled)
return true;
return false;
}
private:
base::ScopedTempDir scoped_base_dir_;
content::TestBrowserThreadBundle thread_bundle_;
TestingProfile profile_;
base::FilePath base_dir_;
FakeAPIUtil* fake_api_util_; // Owned by |sync_service_|.
DriveMetadataStore* metadata_store_; // Owned by |sync_service_|.
scoped_ptr<DriveFileSyncService> sync_service_;
DISALLOW_COPY_AND_ASSIGN(DriveFileSyncServiceTest);
};
TEST_F(DriveFileSyncServiceTest, UninstallOrigin) {
// Add fake app origin directory using fake drive_sync_client.
std::string origin_dir_resource_id = "uninstalledappresourceid";
fake_api_util()->PushRemoteChange("parent_id",
"parent_title",
"uninstall_me_folder",
origin_dir_resource_id,
"resource_md5",
SYNC_FILE_TYPE_FILE,
false);
// Add meta_data entry so GURL->resourse_id mapping is there.
const GURL origin_gurl("chrome-extension://uninstallme");
metadata_store()->AddIncrementalSyncOrigin(origin_gurl,
origin_dir_resource_id);
// Delete the origin directory.
bool done = false;
sync_service()->UninstallOrigin(
origin_gurl,
base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(done);
// Assert the App's origin folder was marked as deleted.
EXPECT_TRUE(fake_api_util()->remote_resources().find(
origin_dir_resource_id)->second.deleted);
}
TEST_F(DriveFileSyncServiceTest, UninstallOriginWithoutOriginDirectory) {
// Not add fake app origin directory.
std::string origin_dir_resource_id = "uninstalledappresourceid";
// Add meta_data entry so GURL->resourse_id mapping is there.
const GURL origin_gurl("chrome-extension://uninstallme");
metadata_store()->AddIncrementalSyncOrigin(origin_gurl,
origin_dir_resource_id);
// Delete the origin directory (but not found).
bool done = false;
sync_service()->UninstallOrigin(
origin_gurl,
base::Bind(&ExpectEqStatus, &done, SYNC_STATUS_OK));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(done);
// Assert the App's origin folder does not exist.
const FakeAPIUtil::RemoteResourceByResourceId& remote_resources =
fake_api_util()->remote_resources();
EXPECT_TRUE(remote_resources.find(origin_dir_resource_id) ==
remote_resources.end());
}
TEST_F(DriveFileSyncServiceTest, DisableOriginPendingOrigin) {
// Disable a pending origin after DriveFileSystemService has already started.
const GURL origin("chrome-extension://app");
std::string origin_resource_id = "app_resource_id";
pending_batch_sync_origins()->insert(std::make_pair(origin,
origin_resource_id));
ASSERT_TRUE(VerifyOriginStatusCount(1u, 0u, 0u));
// Pending origins that are disabled are dropped and do not go to disabled.
sync_service()->DisableOrigin(origin, base::Bind(&ExpectOkStatus));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 0u));
}
TEST_F(DriveFileSyncServiceTest,
DisableOriginIncrementalOrigin) {
// Disable a pending origin after DriveFileSystemService has already started.
const GURL origin("chrome-extension://app");
std::string origin_resource_id = "app_resource_id";
metadata_store()->AddIncrementalSyncOrigin(origin, origin_resource_id);
ASSERT_TRUE(VerifyOriginStatusCount(0u, 1u, 0u));
sync_service()->DisableOrigin(origin, base::Bind(&ExpectOkStatus));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 1u));
}
TEST_F(DriveFileSyncServiceTest, EnableOrigin) {
const GURL origin("chrome-extension://app");
std::string origin_resource_id = "app_resource_id";
metadata_store()->AddIncrementalSyncOrigin(origin, origin_resource_id);
metadata_store()->DisableOrigin(origin, base::Bind(&ExpectOkStatus));
ASSERT_TRUE(VerifyOriginStatusCount(0u, 0u, 1u));
// Re-enable the previously disabled origin. It initially goes to pending
// status and then to enabled (incremental) again when NotifyTasksDone() in
// SyncTaskManager invokes MaybeStartFetchChanges() and pending
// origins > 0.
sync_service()->EnableOrigin(origin, base::Bind(&ExpectOkStatus));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(VerifyOriginStatusCount(0u, 1u, 0u));
}
TEST_F(DriveFileSyncServiceTest, GetOriginStatusMap) {
RemoteFileSyncService::OriginStatusMap origin_status_map;
sync_service()->GetOriginStatusMap(&origin_status_map);
ASSERT_EQ(0u, origin_status_map.size());
// Add 3 pending, 2 enabled and 1 disabled sync origin.
AddOrigin("Pending", "p0");
AddOrigin("Pending", "p1");
AddOrigin("Pending", "p2");
AddOrigin("Enabled", "e0");
AddOrigin("Enabled", "e1");
AddOrigin("Disabled", "d0");
sync_service()->GetOriginStatusMap(&origin_status_map);
ASSERT_EQ(6u, origin_status_map.size());
EXPECT_EQ("Pending", origin_status_map[GURL("chrome-extension://app_p0")]);
EXPECT_EQ("Pending", origin_status_map[GURL("chrome-extension://app_p1")]);
EXPECT_EQ("Pending", origin_status_map[GURL("chrome-extension://app_p2")]);
EXPECT_EQ("Enabled", origin_status_map[GURL("chrome-extension://app_e0")]);
EXPECT_EQ("Enabled", origin_status_map[GURL("chrome-extension://app_e1")]);
EXPECT_EQ("Disabled", origin_status_map[GURL("chrome-extension://app_d0")]);
}
} // namespace sync_file_system