Commit 53add353 authored by peria@chromium.org's avatar peria@chromium.org

[SyncFS] Make SyncEngineTest multi-threaded test.

Main target of this test is communication between
SyncEngine in UI thread and SyncWorker in a worker thread.


BUG=378621
TEST=./unit_tests --gtest_filter="SyncEngineTest.*"

Review URL: https://codereview.chromium.org/335473004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278680 0039d316-1c4b-4281-b951-d872f2087c98
parent 4d73c7d7
...@@ -5,346 +5,226 @@ ...@@ -5,346 +5,226 @@
#include "chrome/browser/sync_file_system/drive_backend/sync_engine.h" #include "chrome/browser/sync_file_system/drive_backend/sync_engine.h"
#include "base/files/scoped_temp_dir.h" #include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/drive/drive_uploader.h" #include "chrome/browser/drive/drive_uploader.h"
#include "chrome/browser/drive/fake_drive_service.h" #include "chrome/browser/drive/fake_drive_service.h"
#include "chrome/browser/extensions/test_extension_service.h" #include "chrome/browser/sync_file_system/drive_backend/callback_helper.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" #include "chrome/browser/sync_file_system/drive_backend/fake_sync_worker.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" #include "chrome/browser/sync_file_system/drive_backend/sync_worker_interface.h"
#include "chrome/browser/sync_file_system/drive_backend/sync_task.h" #include "chrome/browser/sync_file_system/remote_file_sync_service.h"
#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
#include "chrome/browser/sync_file_system/drive_backend/sync_worker.h"
#include "chrome/browser/sync_file_system/sync_file_system_test_util.h" #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_browser_thread_bundle.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/value_builder.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
#include "third_party/leveldatabase/src/include/leveldb/env.h"
namespace sync_file_system { namespace sync_file_system {
namespace drive_backend { namespace drive_backend {
namespace { class SyncEngineTest : public testing::Test,
public base::SupportsWeakPtr<SyncEngineTest> {
const char kAppID[] = "app_id";
void EmptyTask(SyncStatusCode status, const SyncStatusCallback& callback) {
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(callback, status));
}
} // namespace
class MockSyncTask : public ExclusiveTask {
public:
explicit MockSyncTask(bool used_network) {
set_used_network(used_network);
}
virtual ~MockSyncTask() {}
virtual void RunExclusive(const SyncStatusCallback& callback) OVERRIDE {
callback.Run(SYNC_STATUS_OK);
}
private:
DISALLOW_COPY_AND_ASSIGN(MockSyncTask);
};
class MockExtensionService : public TestExtensionService {
public: public:
MockExtensionService() {} typedef RemoteFileSyncService::OriginStatusMap RemoteOriginStatusMap;
virtual ~MockExtensionService() {}
virtual const extensions::ExtensionSet* extensions() const OVERRIDE {
return &extensions_;
}
virtual void AddExtension(const extensions::Extension* extension) OVERRIDE {
extensions_.Insert(make_scoped_refptr(extension));
}
virtual const extensions::Extension* GetInstalledExtension(
const std::string& extension_id) const OVERRIDE {
return extensions_.GetByID(extension_id);
}
virtual bool IsExtensionEnabled(
const std::string& extension_id) const OVERRIDE {
return extensions_.Contains(extension_id) &&
!disabled_extensions_.Contains(extension_id);
}
void UninstallExtension(const std::string& extension_id) {
extensions_.Remove(extension_id);
disabled_extensions_.Remove(extension_id);
}
void DisableExtension(const std::string& extension_id) {
if (!IsExtensionEnabled(extension_id))
return;
const extensions::Extension* extension = extensions_.GetByID(extension_id);
disabled_extensions_.Insert(make_scoped_refptr(extension));
}
private:
extensions::ExtensionSet extensions_;
extensions::ExtensionSet disabled_extensions_;
DISALLOW_COPY_AND_ASSIGN(MockExtensionService);
};
class SyncEngineTest
: public testing::Test,
public base::SupportsWeakPtr<SyncEngineTest> {
public:
SyncEngineTest() {} SyncEngineTest() {}
virtual ~SyncEngineTest() {} virtual ~SyncEngineTest() {}
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
extension_service_.reset(new MockExtensionService);
scoped_ptr<drive::DriveServiceInterface> scoped_ptr<drive::DriveServiceInterface>
fake_drive_service(new drive::FakeDriveService); fake_drive_service(new drive::FakeDriveService);
worker_pool_ = new base::SequencedWorkerPool(1, "Worker");
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner =
base::MessageLoopProxy::current();
worker_task_runner_ =
worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
worker_pool_->GetSequenceToken(),
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
sync_engine_.reset(new drive_backend::SyncEngine( sync_engine_.reset(new drive_backend::SyncEngine(
base::MessageLoopProxy::current(), // ui_task_runner ui_task_runner,
base::MessageLoopProxy::current(), // worker_task_runner worker_task_runner_,
base::MessageLoopProxy::current(), // file_task_runner NULL /* file_task_runner */,
base::MessageLoopProxy::current(), // drive_task_runner NULL /* drive_task_runner */,
profile_dir_.path(), profile_dir_.path(),
NULL, // task_logger NULL /* task_logger */,
NULL, // notification_manager NULL /* notification_manager */,
extension_service_.get(), NULL /* extension_service */,
NULL, // signin_manager NULL /* signin_manager */,
NULL, // token_service NULL /* token_service */,
NULL, // request_context NULL /* request_context */,
in_memory_env_.get())); NULL /* in_memory_env */));
sync_engine_->InitializeForTesting( sync_engine_->InitializeForTesting(
fake_drive_service.Pass(), fake_drive_service.Pass(),
scoped_ptr<drive::DriveUploaderInterface>(), scoped_ptr<drive::DriveUploaderInterface>(),
scoped_ptr<SyncWorkerInterface>()); scoped_ptr<SyncWorkerInterface>(new FakeSyncWorker));
sync_engine_->SetSyncEnabled(true); sync_engine_->SetSyncEnabled(true);
base::RunLoop().RunUntilIdle();
WaitForWorkerTaskRunner();
} }
virtual void TearDown() OVERRIDE { virtual void TearDown() OVERRIDE {
sync_engine_.reset(); sync_engine_.reset();
extension_service_.reset(); WaitForWorkerTaskRunner();
worker_pool_->Shutdown();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
MockExtensionService* extension_service() { return extension_service_.get(); } bool FindOriginStatus(const GURL& origin, std::string* status) {
SyncEngine* sync_engine() { return sync_engine_.get(); } scoped_ptr<RemoteOriginStatusMap> status_map;
sync_engine()->GetOriginStatusMap(CreateResultReceiver(&status_map));
WaitForWorkerTaskRunner();
RemoteOriginStatusMap::const_iterator itr = status_map->find(origin);
if (itr == status_map->end())
return false;
SyncTaskManager* GetSyncTaskManager() { *status = itr->second;
return sync_engine_->sync_worker_->GetSyncTaskManager(); // If an origin is uninstalled, it should not be found actually.
if (*status == "Uninstalled")
return false;
return true;
} }
void CheckServiceState(SyncStatusCode expected_sync_status, void PostUpdateServiceState(RemoteServiceState state,
RemoteServiceState expected_service_status, const std::string& description) {
SyncStatusCode sync_status) { worker_task_runner_->PostTask(
EXPECT_EQ(expected_sync_status, sync_status); FROM_HERE,
EXPECT_EQ(expected_service_status, sync_engine_->GetCurrentState()); base::Bind(&FakeSyncWorker::UpdateServiceState,
base::Unretained(fake_sync_worker()),
state,
description));
WaitForWorkerTaskRunner();
} }
MetadataDatabase* metadata_database() { void WaitForWorkerTaskRunner() {
return sync_engine_->sync_worker_->GetMetadataDatabase(); DCHECK(worker_task_runner_);
base::RunLoop run_loop;
worker_task_runner_->PostTask(
FROM_HERE,
RelayCallbackToCurrentThread(
FROM_HERE, run_loop.QuitClosure()));
run_loop.Run();
} }
void SetHasRefreshToken(bool has_refresh_token) { // Accessors
sync_engine_->sync_worker_->SetHasRefreshToken(has_refresh_token); SyncEngine* sync_engine() { return sync_engine_.get(); }
FakeSyncWorker* fake_sync_worker() {
return static_cast<FakeSyncWorker*>(sync_engine_->sync_worker_.get());
} }
private: private:
content::TestBrowserThreadBundle browser_threads_; content::TestBrowserThreadBundle browser_threads_;
base::ScopedTempDir profile_dir_; base::ScopedTempDir profile_dir_;
scoped_ptr<leveldb::Env> in_memory_env_;
scoped_ptr<MockExtensionService> extension_service_;
scoped_ptr<drive_backend::SyncEngine> sync_engine_; scoped_ptr<drive_backend::SyncEngine> sync_engine_;
scoped_refptr<base::SequencedWorkerPool> worker_pool_;
scoped_refptr<base::SequencedTaskRunner> worker_task_runner_;
DISALLOW_COPY_AND_ASSIGN(SyncEngineTest); DISALLOW_COPY_AND_ASSIGN(SyncEngineTest);
}; };
TEST_F(SyncEngineTest, EnableOrigin) { TEST_F(SyncEngineTest, OriginTest) {
FileTracker tracker; GURL origin("chrome-extension://app_0");
SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
sync_engine()->RegisterOrigin(origin, CreateResultReceiver(&sync_status)); SyncStatusCode sync_status;
base::RunLoop().RunUntilIdle(); std::string status;
sync_engine()->RegisterOrigin(
origin,
CreateResultReceiver(&sync_status));
WaitForWorkerTaskRunner();
EXPECT_EQ(SYNC_STATUS_OK, sync_status); EXPECT_EQ(SYNC_STATUS_OK, sync_status);
ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID, &tracker)); ASSERT_TRUE(FindOriginStatus(origin, &status));
EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind()); EXPECT_EQ("Registered", status);
sync_engine()->DisableOrigin(origin, CreateResultReceiver(&sync_status)); sync_engine()->DisableOrigin(
base::RunLoop().RunUntilIdle(); origin,
CreateResultReceiver(&sync_status));
WaitForWorkerTaskRunner();
EXPECT_EQ(SYNC_STATUS_OK, sync_status); EXPECT_EQ(SYNC_STATUS_OK, sync_status);
ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID, &tracker)); ASSERT_TRUE(FindOriginStatus(origin, &status));
EXPECT_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker.tracker_kind()); EXPECT_EQ("Disabled", status);
sync_engine()->EnableOrigin(origin, CreateResultReceiver(&sync_status)); sync_engine()->EnableOrigin(
base::RunLoop().RunUntilIdle(); origin,
CreateResultReceiver(&sync_status));
WaitForWorkerTaskRunner();
EXPECT_EQ(SYNC_STATUS_OK, sync_status); EXPECT_EQ(SYNC_STATUS_OK, sync_status);
ASSERT_TRUE(metadata_database()->FindAppRootTracker(kAppID, &tracker)); ASSERT_TRUE(FindOriginStatus(origin, &status));
EXPECT_EQ(TRACKER_KIND_APP_ROOT, tracker.tracker_kind()); EXPECT_EQ("Enabled", status);
sync_engine()->UninstallOrigin( sync_engine()->UninstallOrigin(
origin, origin,
RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE, RemoteFileSyncService::UNINSTALL_AND_KEEP_REMOTE,
CreateResultReceiver(&sync_status)); CreateResultReceiver(&sync_status));
base::RunLoop().RunUntilIdle(); WaitForWorkerTaskRunner();
EXPECT_EQ(SYNC_STATUS_OK, sync_status); EXPECT_EQ(SYNC_STATUS_OK, sync_status);
ASSERT_FALSE(metadata_database()->FindAppRootTracker(kAppID, &tracker)); EXPECT_FALSE(FindOriginStatus(origin, &status));
EXPECT_EQ("Uninstalled", status);
} }
TEST_F(SyncEngineTest, GetOriginStatusMap) { TEST_F(SyncEngineTest, GetOriginStatusMap) {
FileTracker tracker;
SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN; SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
GURL origin = extensions::Extension::GetBaseURLFromExtensionId(kAppID);
sync_engine()->RegisterOrigin(GURL("chrome-extension://app_0"), sync_engine()->RegisterOrigin(GURL("chrome-extension://app_0"),
CreateResultReceiver(&sync_status)); CreateResultReceiver(&sync_status));
base::RunLoop().RunUntilIdle(); WaitForWorkerTaskRunner();
EXPECT_EQ(SYNC_STATUS_OK, sync_status); EXPECT_EQ(SYNC_STATUS_OK, sync_status);
sync_engine()->RegisterOrigin(GURL("chrome-extension://app_1"), sync_engine()->RegisterOrigin(GURL("chrome-extension://app_1"),
CreateResultReceiver(&sync_status)); CreateResultReceiver(&sync_status));
base::RunLoop().RunUntilIdle(); WaitForWorkerTaskRunner();
EXPECT_EQ(SYNC_STATUS_OK, sync_status); EXPECT_EQ(SYNC_STATUS_OK, sync_status);
scoped_ptr<RemoteFileSyncService::OriginStatusMap> status_map; scoped_ptr<RemoteOriginStatusMap> status_map;
sync_engine()->GetOriginStatusMap(CreateResultReceiver(&status_map)); sync_engine()->GetOriginStatusMap(CreateResultReceiver(&status_map));
base::RunLoop().RunUntilIdle(); WaitForWorkerTaskRunner();
ASSERT_EQ(2u, status_map->size()); ASSERT_EQ(2u, status_map->size());
EXPECT_EQ("Enabled", (*status_map)[GURL("chrome-extension://app_0")]); EXPECT_EQ("Registered", (*status_map)[GURL("chrome-extension://app_0")]);
EXPECT_EQ("Enabled", (*status_map)[GURL("chrome-extension://app_1")]); EXPECT_EQ("Registered", (*status_map)[GURL("chrome-extension://app_1")]);
sync_engine()->DisableOrigin(GURL("chrome-extension://app_1"), sync_engine()->DisableOrigin(GURL("chrome-extension://app_1"),
CreateResultReceiver(&sync_status)); CreateResultReceiver(&sync_status));
base::RunLoop().RunUntilIdle(); WaitForWorkerTaskRunner();
EXPECT_EQ(SYNC_STATUS_OK, sync_status); EXPECT_EQ(SYNC_STATUS_OK, sync_status);
sync_engine()->GetOriginStatusMap(CreateResultReceiver(&status_map)); sync_engine()->GetOriginStatusMap(CreateResultReceiver(&status_map));
base::RunLoop().RunUntilIdle(); WaitForWorkerTaskRunner();
ASSERT_EQ(2u, status_map->size()); ASSERT_EQ(2u, status_map->size());
EXPECT_EQ("Enabled", (*status_map)[GURL("chrome-extension://app_0")]); EXPECT_EQ("Registered", (*status_map)[GURL("chrome-extension://app_0")]);
EXPECT_EQ("Disabled", (*status_map)[GURL("chrome-extension://app_1")]); EXPECT_EQ("Disabled", (*status_map)[GURL("chrome-extension://app_1")]);
} }
TEST_F(SyncEngineTest, UpdateServiceState) { TEST_F(SyncEngineTest, UpdateServiceState) {
EXPECT_EQ(REMOTE_SERVICE_OK, sync_engine()->GetCurrentState()); struct {
RemoteServiceState state;
// Assume an user is in login state. const char* description;
sync_engine()->OnReadyToSendRequests(); } test_data[] = {
{REMOTE_SERVICE_OK, "OK"},
GetSyncTaskManager()->ScheduleTask( {REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, "TEMPORARY_UNAVAILABLE"},
FROM_HERE, {REMOTE_SERVICE_AUTHENTICATION_REQUIRED, "AUTHENTICATION_REQUIRED"},
base::Bind(&EmptyTask, SYNC_STATUS_AUTHENTICATION_FAILED), {REMOTE_SERVICE_DISABLED, "DISABLED"},
SyncTaskManager::PRIORITY_MED, };
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(), for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
SYNC_STATUS_AUTHENTICATION_FAILED, PostUpdateServiceState(test_data[i].state, test_data[i].description);
REMOTE_SERVICE_AUTHENTICATION_REQUIRED)); EXPECT_EQ(test_data[i].state, sync_engine()->GetCurrentState())
<< "Expected state: REMOTE_SERVICE_" << test_data[i].description;
GetSyncTaskManager()->ScheduleTask( }
FROM_HERE, }
base::Bind(&EmptyTask, SYNC_STATUS_ACCESS_FORBIDDEN),
SyncTaskManager::PRIORITY_MED, TEST_F(SyncEngineTest, ProcessRemoteChange) {
base::Bind(&SyncEngineTest::CheckServiceState, SyncStatusCode sync_status;
AsWeakPtr(), fileapi::FileSystemURL url;
SYNC_STATUS_ACCESS_FORBIDDEN, sync_engine()->ProcessRemoteChange(CreateResultReceiver(&sync_status, &url));
REMOTE_SERVICE_AUTHENTICATION_REQUIRED)); WaitForWorkerTaskRunner();
EXPECT_EQ(SYNC_STATUS_OK, sync_status);
GetSyncTaskManager()->ScheduleTask(
FROM_HERE,
base::Bind(&EmptyTask, SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE),
SyncTaskManager::PRIORITY_MED,
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(),
SYNC_STATUS_SERVICE_TEMPORARILY_UNAVAILABLE,
REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
GetSyncTaskManager()->ScheduleTask(
FROM_HERE,
base::Bind(&EmptyTask, SYNC_STATUS_NETWORK_ERROR),
SyncTaskManager::PRIORITY_MED,
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(),
SYNC_STATUS_NETWORK_ERROR,
REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
GetSyncTaskManager()->ScheduleTask(
FROM_HERE,
base::Bind(&EmptyTask, SYNC_STATUS_ABORT),
SyncTaskManager::PRIORITY_MED,
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(),
SYNC_STATUS_ABORT,
REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
GetSyncTaskManager()->ScheduleTask(
FROM_HERE,
base::Bind(&EmptyTask, SYNC_STATUS_FAILED),
SyncTaskManager::PRIORITY_MED,
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(),
SYNC_STATUS_FAILED,
REMOTE_SERVICE_TEMPORARY_UNAVAILABLE));
GetSyncTaskManager()->ScheduleTask(
FROM_HERE,
base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_CORRUPTION),
SyncTaskManager::PRIORITY_MED,
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(),
SYNC_DATABASE_ERROR_CORRUPTION,
REMOTE_SERVICE_DISABLED));
GetSyncTaskManager()->ScheduleTask(
FROM_HERE,
base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_IO_ERROR),
SyncTaskManager::PRIORITY_MED,
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(),
SYNC_DATABASE_ERROR_IO_ERROR,
REMOTE_SERVICE_DISABLED));
GetSyncTaskManager()->ScheduleTask(
FROM_HERE,
base::Bind(&EmptyTask, SYNC_DATABASE_ERROR_FAILED),
SyncTaskManager::PRIORITY_MED,
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(),
SYNC_DATABASE_ERROR_FAILED,
REMOTE_SERVICE_DISABLED));
GetSyncTaskManager()->ScheduleSyncTask(
FROM_HERE,
scoped_ptr<SyncTask>(new MockSyncTask(false)),
SyncTaskManager::PRIORITY_MED,
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(),
SYNC_STATUS_OK,
REMOTE_SERVICE_DISABLED));
GetSyncTaskManager()->ScheduleSyncTask(
FROM_HERE,
scoped_ptr<SyncTask>(new MockSyncTask(true)),
SyncTaskManager::PRIORITY_MED,
base::Bind(&SyncEngineTest::CheckServiceState,
AsWeakPtr(),
SYNC_STATUS_OK,
REMOTE_SERVICE_OK));
base::RunLoop().RunUntilIdle();
} }
} // namespace drive_backend } // namespace drive_backend
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment