• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SyncSharedChangeProcessorTest()34   SyncSharedChangeProcessorTest() : backend_thread_("dbthread"),
35                                     did_connect_(false) {}
36 
~SyncSharedChangeProcessorTest()37   virtual ~SyncSharedChangeProcessorTest() {
38     EXPECT_FALSE(db_syncable_service_.get());
39   }
40 
GetSyncableServiceForType(syncer::ModelType type)41   virtual base::WeakPtr<syncer::SyncableService> GetSyncableServiceForType(
42       syncer::ModelType type) OVERRIDE {
43     return db_syncable_service_->AsWeakPtr();
44   }
45 
CreateAttachmentService(syncer::AttachmentService::Delegate * delegate)46   virtual scoped_ptr<syncer::AttachmentService> CreateAttachmentService(
47       syncer::AttachmentService::Delegate* delegate) OVERRIDE {
48     return syncer::AttachmentServiceImpl::CreateForTest();
49   }
50 
51  protected:
SetUp()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 
TearDown()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.
Connect()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().
SetUpDBSyncableService()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().
TearDownDBSyncableService()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()).
ConnectOnDBThread(const scoped_refptr<SharedChangeProcessor> & shared_change_processor)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.
TEST_F(SyncSharedChangeProcessorTest,Basic)138 TEST_F(SyncSharedChangeProcessorTest, Basic) {
139   Connect();
140 }
141 
142 }  // namespace
143 
144 }  // namespace browser_sync
145