blob: eed132c07142d828eeadd0244d93e238f0872c7b [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/sync/glue/sync_backend_registrar.h"
#include "chrome/browser/sync/glue/change_processor_mock.h"
#include "chrome/browser/sync/glue/ui_model_worker.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h"
#include "sync/internal_api/public/base/model_type.h"
#include "sync/internal_api/public/test/test_user_share.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace browser_sync {
namespace {
using ::testing::_;
using ::testing::InSequence;
using ::testing::Return;
using ::testing::StrictMock;
using content::BrowserThread;
using syncer::FIRST_REAL_MODEL_TYPE;
using syncer::AUTOFILL;
using syncer::BOOKMARKS;
using syncer::PREFERENCES;
using syncer::THEMES;
using syncer::NIGORI;
using syncer::PASSWORDS;
using syncer::MODEL_TYPE_COUNT;
using syncer::ModelTypeSet;
using syncer::ModelType;
using syncer::ModelTypeFromInt;
void TriggerChanges(SyncBackendRegistrar* registrar, ModelType type) {
registrar->OnChangesApplied(type, 0, NULL,
syncer::ImmutableChangeRecordList());
registrar->OnChangesComplete(type);
}
class SyncBackendRegistrarTest : public testing::Test {
public:
void TestNonUIDataTypeActivationAsync(ChangeProcessor* processor,
base::WaitableEvent* done) {
registrar_->ActivateDataType(AUTOFILL,
syncer::GROUP_DB,
processor,
test_user_share_.user_share());
syncer::ModelSafeRoutingInfo expected_routing_info;
expected_routing_info[AUTOFILL] = syncer::GROUP_DB;
ExpectRoutingInfo(registrar_.get(), expected_routing_info);
ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet(AUTOFILL));
TriggerChanges(registrar_.get(), AUTOFILL);
done->Signal();
}
protected:
SyncBackendRegistrarTest() :
sync_thread_(NULL),
ui_thread_(BrowserThread::UI, &ui_loop_),
db_thread_(BrowserThread::DB),
file_thread_(BrowserThread::FILE),
io_thread_(BrowserThread::IO) {}
virtual ~SyncBackendRegistrarTest() {}
virtual void SetUp() {
db_thread_.Start();
file_thread_.Start();
io_thread_.Start();
test_user_share_.SetUp();
registrar_.reset(new SyncBackendRegistrar("test", &profile_,
scoped_ptr<base::Thread>()));
sync_thread_ = registrar_->sync_thread();
}
virtual void TearDown() {
registrar_->RequestWorkerStopOnUIThread();
test_user_share_.TearDown();
sync_thread_->message_loop()->PostTask(
FROM_HERE,
base::Bind(&SyncBackendRegistrar::Shutdown,
base::Unretained(registrar_.release())));
sync_thread_->message_loop()->RunUntilIdle();
io_thread_.Stop();
file_thread_.Stop();
db_thread_.Stop();
}
void ExpectRoutingInfo(
SyncBackendRegistrar* registrar,
const syncer::ModelSafeRoutingInfo& expected_routing_info) {
syncer::ModelSafeRoutingInfo routing_info;
registrar->GetModelSafeRoutingInfo(&routing_info);
EXPECT_EQ(expected_routing_info, routing_info);
}
void ExpectHasProcessorsForTypes(const SyncBackendRegistrar& registrar,
ModelTypeSet types) {
for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
ModelType model_type = ModelTypeFromInt(i);
EXPECT_EQ(types.Has(model_type),
registrar_->IsTypeActivatedForTest(model_type));
}
}
base::MessageLoop ui_loop_;
syncer::TestUserShare test_user_share_;
TestingProfile profile_;
scoped_ptr<SyncBackendRegistrar> registrar_;
base::Thread* sync_thread_;
content::TestBrowserThread ui_thread_;
content::TestBrowserThread db_thread_;
content::TestBrowserThread file_thread_;
content::TestBrowserThread io_thread_;
};
TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) {
registrar_->SetInitialTypes(ModelTypeSet());
EXPECT_FALSE(registrar_->IsNigoriEnabled());
{
std::vector<syncer::ModelSafeWorker*> workers;
registrar_->GetWorkers(&workers);
EXPECT_EQ(4u, workers.size());
}
ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
}
TEST_F(SyncBackendRegistrarTest, ConstructorNonEmpty) {
const ModelTypeSet initial_types(BOOKMARKS, NIGORI, PASSWORDS);
registrar_->SetInitialTypes(initial_types);
EXPECT_TRUE(registrar_->IsNigoriEnabled());
{
std::vector<syncer::ModelSafeWorker*> workers;
registrar_->GetWorkers(&workers);
EXPECT_EQ(4u, workers.size());
}
{
syncer::ModelSafeRoutingInfo expected_routing_info;
expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
// Passwords dropped because of no password store.
ExpectRoutingInfo(registrar_.get(), expected_routing_info);
}
ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
}
TEST_F(SyncBackendRegistrarTest, ConfigureDataTypes) {
registrar_->SetInitialTypes(ModelTypeSet());
// Add.
const ModelTypeSet types1(BOOKMARKS, NIGORI, AUTOFILL);
EXPECT_TRUE(
registrar_->ConfigureDataTypes(types1, ModelTypeSet()).Equals(types1));
{
syncer::ModelSafeRoutingInfo expected_routing_info;
expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
expected_routing_info[AUTOFILL] = syncer::GROUP_PASSIVE;
ExpectRoutingInfo(registrar_.get(), expected_routing_info);
}
ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
EXPECT_TRUE(types1.Equals(registrar_->GetLastConfiguredTypes()));
// Add and remove.
const ModelTypeSet types2(PREFERENCES, THEMES);
EXPECT_TRUE(registrar_->ConfigureDataTypes(types2, types1).Equals(types2));
{
syncer::ModelSafeRoutingInfo expected_routing_info;
expected_routing_info[PREFERENCES] = syncer::GROUP_PASSIVE;
expected_routing_info[THEMES] = syncer::GROUP_PASSIVE;
ExpectRoutingInfo(registrar_.get(), expected_routing_info);
}
ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
EXPECT_TRUE(types2.Equals(registrar_->GetLastConfiguredTypes()));
// Remove.
EXPECT_TRUE(registrar_->ConfigureDataTypes(ModelTypeSet(), types2).Empty());
ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
EXPECT_TRUE(ModelTypeSet().Equals(registrar_->GetLastConfiguredTypes()));
}
TEST_F(SyncBackendRegistrarTest, ActivateDeactivateUIDataType) {
InSequence in_sequence;
registrar_->SetInitialTypes(ModelTypeSet());
// Should do nothing.
TriggerChanges(registrar_.get(), BOOKMARKS);
StrictMock<ChangeProcessorMock> change_processor_mock;
EXPECT_CALL(change_processor_mock, StartImpl(&profile_));
EXPECT_CALL(change_processor_mock, IsRunning())
.WillRepeatedly(Return(true));
EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
EXPECT_CALL(change_processor_mock, IsRunning())
.WillRepeatedly(Return(true));
EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
EXPECT_CALL(change_processor_mock, IsRunning())
.WillRepeatedly(Return(false));
const ModelTypeSet types(BOOKMARKS);
EXPECT_TRUE(
registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
registrar_->ActivateDataType(BOOKMARKS, syncer::GROUP_UI,
&change_processor_mock,
test_user_share_.user_share());
{
syncer::ModelSafeRoutingInfo expected_routing_info;
expected_routing_info[BOOKMARKS] = syncer::GROUP_UI;
ExpectRoutingInfo(registrar_.get(), expected_routing_info);
}
ExpectHasProcessorsForTypes(*registrar_, types);
TriggerChanges(registrar_.get(), BOOKMARKS);
registrar_->DeactivateDataType(BOOKMARKS);
ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
// Should do nothing.
TriggerChanges(registrar_.get(), BOOKMARKS);
}
void ActiviateDoneOnDb(base::WaitableEvent* done) {
done->Signal();
}
TEST_F(SyncBackendRegistrarTest, ActivateDeactivateNonUIDataType) {
InSequence in_sequence;
registrar_->SetInitialTypes(ModelTypeSet());
// Should do nothing.
TriggerChanges(registrar_.get(), AUTOFILL);
StrictMock<ChangeProcessorMock> change_processor_mock;
EXPECT_CALL(change_processor_mock, StartImpl(&profile_));
EXPECT_CALL(change_processor_mock, IsRunning())
.WillRepeatedly(Return(true));
EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
EXPECT_CALL(change_processor_mock, IsRunning())
.WillRepeatedly(Return(true));
EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
EXPECT_CALL(change_processor_mock, IsRunning())
.WillRepeatedly(Return(false));
const ModelTypeSet types(AUTOFILL);
EXPECT_TRUE(
registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
base::WaitableEvent done(false, false);
BrowserThread::PostTask(
BrowserThread::DB,
FROM_HERE,
base::Bind(&SyncBackendRegistrarTest::TestNonUIDataTypeActivationAsync,
base::Unretained(this),
&change_processor_mock,
&done));
done.Wait();
registrar_->DeactivateDataType(AUTOFILL);
ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
// Should do nothing.
TriggerChanges(registrar_.get(), AUTOFILL);
}
} // namespace
} // namespace browser_sync