1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
|
// 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 "components/sync/driver/shared_change_processor.h"
#include <cstddef>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/memory/ptr_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "components/sync/base/model_type.h"
#include "components/sync/device_info/local_device_info_provider.h"
#include "components/sync/driver/fake_sync_client.h"
#include "components/sync/driver/generic_change_processor.h"
#include "components/sync/driver/generic_change_processor_factory.h"
#include "components/sync/driver/sync_api_component_factory.h"
#include "components/sync/model/attachments/attachment_id.h"
#include "components/sync/model/attachments/attachment_service.h"
#include "components/sync/model/attachments/attachment_store.h"
#include "components/sync/model/data_type_error_handler_mock.h"
#include "components/sync/model/fake_syncable_service.h"
#include "components/sync/syncable/test_user_share.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
namespace {
using ::testing::NiceMock;
using ::testing::StrictMock;
class TestSyncApiComponentFactory : public SyncApiComponentFactory {
public:
TestSyncApiComponentFactory() {}
~TestSyncApiComponentFactory() override {}
// SyncApiComponentFactory implementation.
void RegisterDataTypes(
SyncService* sync_service,
const RegisterDataTypesMethod& register_platform_types_method) override {}
DataTypeManager* CreateDataTypeManager(
ModelTypeSet initial_types,
const WeakHandle<DataTypeDebugInfoListener>& debug_info_listener,
const DataTypeController::TypeMap* controllers,
const DataTypeEncryptionHandler* encryption_handler,
ModelTypeConfigurer* configurer,
DataTypeManagerObserver* observer) override {
return nullptr;
}
SyncEngine* CreateSyncEngine(const std::string& name,
invalidation::InvalidationService* invalidator,
const base::WeakPtr<SyncPrefs>& sync_prefs,
const base::FilePath& sync_folder) override {
return nullptr;
}
std::unique_ptr<LocalDeviceInfoProvider> CreateLocalDeviceInfoProvider()
override {
return nullptr;
}
SyncApiComponentFactory::SyncComponents CreateBookmarkSyncComponents(
SyncService* sync_service,
std::unique_ptr<DataTypeErrorHandler> error_handler) override {
return SyncApiComponentFactory::SyncComponents(nullptr, nullptr);
}
std::unique_ptr<AttachmentService> CreateAttachmentService(
std::unique_ptr<AttachmentStoreForSync> attachment_store,
const UserShare& user_share,
const std::string& store_birthday,
ModelType model_type,
AttachmentService::Delegate* delegate) override {
return AttachmentService::CreateForTest();
}
};
class SyncSharedChangeProcessorTest : public testing::Test,
public FakeSyncClient {
public:
SyncSharedChangeProcessorTest()
: FakeSyncClient(&factory_),
model_thread_("dbthread"),
did_connect_(false),
has_attachment_service_(false) {}
~SyncSharedChangeProcessorTest() override {
EXPECT_FALSE(db_syncable_service_.get());
}
// FakeSyncClient override.
base::WeakPtr<SyncableService> GetSyncableServiceForType(
ModelType type) override {
return db_syncable_service_->AsWeakPtr();
}
protected:
void SetUp() override {
test_user_share_.SetUp();
shared_change_processor_ = new SharedChangeProcessor(AUTOFILL);
ASSERT_TRUE(model_thread_.Start());
ASSERT_TRUE(model_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&SyncSharedChangeProcessorTest::SetUpDBSyncableService,
base::Unretained(this))));
}
void TearDown() override {
EXPECT_TRUE(model_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&SyncSharedChangeProcessorTest::TearDownDBSyncableService,
base::Unretained(this))));
// This must happen before the DB thread is stopped since
// |shared_change_processor_| may post tasks to delete its members
// on the correct thread.
//
// TODO(akalin): Write deterministic tests for the destruction of
// |shared_change_processor_| on the UI and DB threads.
shared_change_processor_ = nullptr;
model_thread_.Stop();
// Note: Stop() joins the threads, and that barrier prevents this read
// from being moved (e.g by compiler optimization) in such a way that it
// would race with the write in ConnectOnDBThread (because by this time,
// everything that could have run on |model_thread_| has done so).
ASSERT_TRUE(did_connect_);
test_user_share_.TearDown();
}
// Connect |shared_change_processor_| on the DB thread.
void Connect() {
EXPECT_TRUE(model_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&SyncSharedChangeProcessorTest::ConnectOnDBThread,
base::Unretained(this), shared_change_processor_)));
}
void SetAttachmentStore() {
EXPECT_TRUE(model_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&SyncSharedChangeProcessorTest::SetAttachmentStoreOnDBThread,
base::Unretained(this))));
}
bool HasAttachmentService() {
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
EXPECT_TRUE(model_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(
&SyncSharedChangeProcessorTest::CheckAttachmentServiceOnDBThread,
base::Unretained(this), base::Unretained(&event))));
event.Wait();
return has_attachment_service_;
}
private:
// Used by SetUp().
void SetUpDBSyncableService() {
DCHECK(model_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(!db_syncable_service_.get());
db_syncable_service_ = base::MakeUnique<FakeSyncableService>();
}
// Used by TearDown().
void TearDownDBSyncableService() {
DCHECK(model_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(db_syncable_service_.get());
db_syncable_service_.reset();
}
void SetAttachmentStoreOnDBThread() {
DCHECK(model_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(db_syncable_service_.get());
db_syncable_service_->set_attachment_store(
AttachmentStore::CreateInMemoryStore());
}
// Used by Connect(). The SharedChangeProcessor is passed in
// because we modify |shared_change_processor_| on the main thread
// (in TearDown()).
void ConnectOnDBThread(
const scoped_refptr<SharedChangeProcessor>& shared_change_processor) {
DCHECK(model_thread_.task_runner()->BelongsToCurrentThread());
EXPECT_TRUE(shared_change_processor->Connect(
this, &processor_factory_, test_user_share_.user_share(),
base::MakeUnique<DataTypeErrorHandlerMock>(),
base::WeakPtr<SyncMergeResult>()));
did_connect_ = true;
}
void CheckAttachmentServiceOnDBThread(base::WaitableEvent* event) {
DCHECK(model_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(db_syncable_service_.get());
has_attachment_service_ = !!db_syncable_service_->attachment_service();
event->Signal();
}
base::MessageLoop frontend_loop_;
base::Thread model_thread_;
TestUserShare test_user_share_;
TestSyncApiComponentFactory factory_;
scoped_refptr<SharedChangeProcessor> shared_change_processor_;
GenericChangeProcessorFactory processor_factory_;
bool did_connect_;
bool has_attachment_service_;
// Used only on DB thread.
std::unique_ptr<FakeSyncableService> db_syncable_service_;
};
// Simply connect the shared change processor. It should succeed, and
// nothing further should happen.
TEST_F(SyncSharedChangeProcessorTest, Basic) {
Connect();
}
// Connect the shared change processor to a syncable service with
// AttachmentStore. Verify that shared change processor implementation
// creates AttachmentService and passes it back to the syncable service.
TEST_F(SyncSharedChangeProcessorTest, ConnectWithAttachmentStore) {
SetAttachmentStore();
Connect();
EXPECT_TRUE(HasAttachmentService());
}
} // namespace
} // namespace syncer
|