1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "components/sync_driver/shared_change_processor.h" 6 7 #include <cstddef> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/compiler_specific.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/threading/thread.h" 14 #include "components/sync_driver/data_type_error_handler_mock.h" 15 #include "components/sync_driver/generic_change_processor.h" 16 #include "components/sync_driver/generic_change_processor_factory.h" 17 #include "components/sync_driver/sync_api_component_factory.h" 18 #include "sync/api/attachments/attachment_service_impl.h" 19 #include "sync/api/fake_syncable_service.h" 20 #include "testing/gmock/include/gmock/gmock.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 namespace browser_sync { 24 25 namespace { 26 27 using ::testing::NiceMock; 28 using ::testing::StrictMock; 29 30 class SyncSharedChangeProcessorTest : 31 public testing::Test, 32 public browser_sync::SyncApiComponentFactory { 33 public: 34 SyncSharedChangeProcessorTest() : backend_thread_("dbthread"), 35 did_connect_(false) {} 36 37 virtual ~SyncSharedChangeProcessorTest() { 38 EXPECT_FALSE(db_syncable_service_.get()); 39 } 40 41 virtual base::WeakPtr<syncer::SyncableService> GetSyncableServiceForType( 42 syncer::ModelType type) OVERRIDE { 43 return db_syncable_service_->AsWeakPtr(); 44 } 45 46 virtual scoped_ptr<syncer::AttachmentService> CreateAttachmentService( 47 syncer::AttachmentService::Delegate* delegate) OVERRIDE { 48 return syncer::AttachmentServiceImpl::CreateForTest(); 49 } 50 51 protected: 52 virtual void SetUp() OVERRIDE { 53 shared_change_processor_ = new SharedChangeProcessor(); 54 ASSERT_TRUE(backend_thread_.Start()); 55 ASSERT_TRUE(backend_thread_.message_loop_proxy()->PostTask( 56 FROM_HERE, 57 base::Bind(&SyncSharedChangeProcessorTest::SetUpDBSyncableService, 58 base::Unretained(this)))); 59 } 60 61 virtual void TearDown() OVERRIDE { 62 EXPECT_TRUE(backend_thread_.message_loop_proxy()->PostTask( 63 FROM_HERE, 64 base::Bind(&SyncSharedChangeProcessorTest::TearDownDBSyncableService, 65 base::Unretained(this)))); 66 // This must happen before the DB thread is stopped since 67 // |shared_change_processor_| may post tasks to delete its members 68 // on the correct thread. 69 // 70 // TODO(akalin): Write deterministic tests for the destruction of 71 // |shared_change_processor_| on the UI and DB threads. 72 shared_change_processor_ = NULL; 73 backend_thread_.Stop(); 74 75 // Note: Stop() joins the threads, and that barrier prevents this read 76 // from being moved (e.g by compiler optimization) in such a way that it 77 // would race with the write in ConnectOnDBThread (because by this time, 78 // everything that could have run on |backend_thread_| has done so). 79 ASSERT_TRUE(did_connect_); 80 } 81 82 // Connect |shared_change_processor_| on the DB thread. 83 void Connect() { 84 EXPECT_TRUE(backend_thread_.message_loop_proxy()->PostTask( 85 FROM_HERE, 86 base::Bind(&SyncSharedChangeProcessorTest::ConnectOnDBThread, 87 base::Unretained(this), 88 shared_change_processor_))); 89 } 90 91 private: 92 // Used by SetUp(). 93 void SetUpDBSyncableService() { 94 DCHECK(backend_thread_.message_loop_proxy()->BelongsToCurrentThread()); 95 DCHECK(!db_syncable_service_.get()); 96 db_syncable_service_.reset(new syncer::FakeSyncableService()); 97 } 98 99 // Used by TearDown(). 100 void TearDownDBSyncableService() { 101 DCHECK(backend_thread_.message_loop_proxy()->BelongsToCurrentThread()); 102 DCHECK(db_syncable_service_.get()); 103 db_syncable_service_.reset(); 104 } 105 106 // Used by Connect(). The SharedChangeProcessor is passed in 107 // because we modify |shared_change_processor_| on the main thread 108 // (in TearDown()). 109 void ConnectOnDBThread( 110 const scoped_refptr<SharedChangeProcessor>& shared_change_processor) { 111 DCHECK(backend_thread_.message_loop_proxy()->BelongsToCurrentThread()); 112 syncer::UserShare share; 113 EXPECT_TRUE(shared_change_processor->Connect( 114 this, 115 &processor_factory_, 116 &share, 117 &error_handler_, 118 syncer::AUTOFILL, 119 base::WeakPtr<syncer::SyncMergeResult>())); 120 did_connect_ = true; 121 } 122 123 base::MessageLoop frontend_loop_; 124 base::Thread backend_thread_; 125 126 scoped_refptr<SharedChangeProcessor> shared_change_processor_; 127 StrictMock<DataTypeErrorHandlerMock> error_handler_; 128 129 GenericChangeProcessorFactory processor_factory_; 130 bool did_connect_; 131 132 // Used only on DB thread. 133 scoped_ptr<syncer::FakeSyncableService> db_syncable_service_; 134 }; 135 136 // Simply connect the shared change processor. It should succeed, and 137 // nothing further should happen. 138 TEST_F(SyncSharedChangeProcessorTest, Basic) { 139 Connect(); 140 } 141 142 } // namespace 143 144 } // namespace browser_sync 145