Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(263)

Side by Side Diff: chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc

Issue 10874096: [Sync] Rework Invalidator-related unit tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix one more Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync/glue/chrome_sync_notification_bridge.h" 5 #include "chrome/browser/sync/glue/chrome_sync_notification_bridge.h"
6 6
7 #include <cstddef> 7 #include <cstddef>
8 8
9 #include "base/bind.h"
9 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/location.h"
10 #include "base/memory/ref_counted.h" 12 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/message_loop_proxy.h"
16 #include "base/run_loop.h"
14 #include "base/sequenced_task_runner.h" 17 #include "base/sequenced_task_runner.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/threading/thread.h" 18 #include "base/threading/thread.h"
18 #include "chrome/common/chrome_notification_types.h" 19 #include "chrome/common/chrome_notification_types.h"
19 #include "chrome/test/base/profile_mock.h" 20 #include "chrome/test/base/profile_mock.h"
20 #include "content/public/browser/notification_details.h" 21 #include "content/public/browser/notification_details.h"
21 #include "content/public/browser/notification_service.h" 22 #include "content/public/browser/notification_service.h"
22 #include "content/public/test/test_browser_thread.h" 23 #include "content/public/test/test_browser_thread.h"
23 #include "sync/internal_api/public/base/model_type.h" 24 #include "sync/internal_api/public/base/model_type.h"
24 #include "sync/internal_api/public/base/model_type_state_map.h" 25 #include "sync/internal_api/public/base/model_type_state_map.h"
25 #include "sync/notifier/invalidation_handler.h" 26 #include "sync/notifier/fake_invalidation_handler.h"
26 #include "sync/notifier/object_id_state_map_test_util.h" 27 #include "sync/notifier/object_id_state_map_test_util.h"
27 #include "testing/gmock/include/gmock/gmock.h" 28 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h" 29 #include "testing/gtest/include/gtest/gtest.h"
29 30
30 namespace browser_sync { 31 namespace browser_sync {
31 namespace { 32 namespace {
32 33
33 using ::testing::Mock;
34 using ::testing::NiceMock; 34 using ::testing::NiceMock;
35 using ::testing::StrictMock;
36 using content::BrowserThread;
37 35
38 // Receives a ChromeSyncNotificationBridge to register to, and an expected 36 // Since all the interesting stuff happens on the sync thread, we have
Nicolas Zea 2012/08/31 17:44:25 Maybe just move it down to be right above the clas
akalin 2012/08/31 21:06:33 Done.
39 // ModelTypeStateMap. ReceivedProperNotification() will return true only 37 // to be careful to use GTest/GMock only on the main thread since they
40 // if the observer has received a notification with the proper source and 38 // are not thread-safe.
41 // state.
42 // Note: Because this object lives on the sync thread, we use a fake
43 // (vs a mock) so we don't have to worry about possible thread safety
44 // issues within GTest/GMock.
45 class FakeInvalidationHandler : public syncer::InvalidationHandler {
46 public:
47 FakeInvalidationHandler(
48 const scoped_refptr<base::SequencedTaskRunner>& sync_task_runner,
49 ChromeSyncNotificationBridge* bridge,
50 const syncer::ObjectIdStateMap& expected_states,
51 syncer::IncomingNotificationSource expected_source)
52 : sync_task_runner_(sync_task_runner),
53 bridge_(bridge),
54 received_improper_notification_(false),
55 notification_count_(0),
56 expected_states_(expected_states),
57 expected_source_(expected_source) {
58 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
59 bridge_->RegisterHandler(this);
60 const syncer::ObjectIdSet& ids =
61 syncer::ObjectIdStateMapToSet(expected_states);
62 bridge_->UpdateRegisteredIds(this, ids);
63 }
64 39
65 virtual ~FakeInvalidationHandler() { 40 // Needed by BlockForSyncThread().
66 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread()); 41 void DoNothing() {}
67 bridge_->UnregisterHandler(this);
68 }
69
70 // InvalidationHandler implementation.
71 virtual void OnIncomingNotification(
72 const syncer::ObjectIdStateMap& id_state_map,
73 syncer::IncomingNotificationSource source) OVERRIDE {
74 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
75 notification_count_++;
76 if (source != expected_source_) {
77 LOG(ERROR) << "Received notification with wrong source";
78 received_improper_notification_ = true;
79 }
80 if (!::testing::Matches(Eq(expected_states_))(id_state_map)) {
81 LOG(ERROR) << "Received wrong state";
82 received_improper_notification_ = true;
83 }
84 }
85 virtual void OnNotificationsEnabled() OVERRIDE {
86 NOTREACHED();
87 }
88 virtual void OnNotificationsDisabled(
89 syncer::NotificationsDisabledReason reason) OVERRIDE {
90 NOTREACHED();
91 }
92
93 bool ReceivedProperNotification() const {
94 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
95 return (notification_count_ == 1) && !received_improper_notification_;
96 }
97
98 private:
99 const scoped_refptr<base::SequencedTaskRunner> sync_task_runner_;
100 ChromeSyncNotificationBridge* const bridge_;
101 bool received_improper_notification_;
102 size_t notification_count_;
103 const syncer::ObjectIdStateMap expected_states_;
104 const syncer::IncomingNotificationSource expected_source_;
105 };
106 42
107 class ChromeSyncNotificationBridgeTest : public testing::Test { 43 class ChromeSyncNotificationBridgeTest : public testing::Test {
108 public: 44 public:
109 ChromeSyncNotificationBridgeTest() 45 ChromeSyncNotificationBridgeTest()
110 : ui_thread_(BrowserThread::UI), 46 : ui_thread_(content::BrowserThread::UI, &ui_loop_),
111 sync_thread_("Sync thread"), 47 sync_thread_("Sync thread"),
112 sync_handler_(NULL), 48 sync_handler_notification_success_(false) {}
113 sync_handler_notification_failure_(false),
114 done_(true, false) {}
115 49
116 virtual ~ChromeSyncNotificationBridgeTest() {} 50 virtual ~ChromeSyncNotificationBridgeTest() {}
117 51
118 protected: 52 protected:
119 virtual void SetUp() OVERRIDE { 53 virtual void SetUp() OVERRIDE {
120 ASSERT_TRUE(sync_thread_.Start()); 54 ASSERT_TRUE(sync_thread_.Start());
121 bridge_.reset( 55 bridge_.reset(
122 new ChromeSyncNotificationBridge( 56 new ChromeSyncNotificationBridge(
123 &mock_profile_, sync_thread_.message_loop_proxy())); 57 &mock_profile_, sync_thread_.message_loop_proxy()));
124 } 58 }
125 59
126 virtual void TearDown() OVERRIDE { 60 virtual void TearDown() OVERRIDE {
127 bridge_->StopForShutdown(); 61 bridge_->StopForShutdown();
128 sync_thread_.Stop(); 62 sync_thread_.Stop();
129 // Must be reset only after the sync thread is stopped. 63 // Must be reset only after the sync thread is stopped.
130 bridge_.reset(); 64 bridge_.reset();
131 EXPECT_EQ(NULL, sync_handler_); 65 EXPECT_EQ(NULL, sync_handler_.get());
132 if (sync_handler_notification_failure_) 66 if (!sync_handler_notification_success_)
133 ADD_FAILURE() << "Sync Observer did not receive proper notification."; 67 ADD_FAILURE() << "Sync handler did not receive proper notification.";
134 } 68 }
135 69
136 void VerifyAndDestroyObserver() { 70 void VerifyAndDestroyObserver(
71 const syncer::ModelTypeStateMap& expected_states,
72 syncer::IncomingNotificationSource expected_source) {
137 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( 73 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
138 FROM_HERE, 74 FROM_HERE,
139 base::Bind(&ChromeSyncNotificationBridgeTest:: 75 base::Bind(&ChromeSyncNotificationBridgeTest::
140 VerifyAndDestroyObserverOnSyncThread, 76 VerifyAndDestroyObserverOnSyncThread,
141 base::Unretained(this)))); 77 base::Unretained(this),
78 expected_states,
79 expected_source)));
142 BlockForSyncThread(); 80 BlockForSyncThread();
143 } 81 }
144 82
145 void CreateObserverWithExpectations( 83 void CreateObserver() {
146 const syncer::ModelTypeStateMap& expected_states,
147 syncer::IncomingNotificationSource expected_source) {
148 const syncer::ObjectIdStateMap& expected_id_state_map =
149 syncer::ModelTypeStateMapToObjectIdStateMap(expected_states);
150 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( 84 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
151 FROM_HERE, 85 FROM_HERE,
152 base::Bind( 86 base::Bind(
153 &ChromeSyncNotificationBridgeTest::CreateObserverOnSyncThread, 87 &ChromeSyncNotificationBridgeTest::CreateObserverOnSyncThread,
154 base::Unretained(this), 88 base::Unretained(this))));
155 expected_id_state_map,
156 expected_source)));
157 BlockForSyncThread(); 89 BlockForSyncThread();
158 } 90 }
159 91
160 void UpdateBridgeEnabledTypes(syncer::ModelTypeSet enabled_types) { 92 void UpdateEnabledTypes(syncer::ModelTypeSet enabled_types) {
161 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( 93 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
162 FROM_HERE, 94 FROM_HERE,
163 base::Bind( 95 base::Bind(
164 &ChromeSyncNotificationBridgeTest:: 96 &ChromeSyncNotificationBridgeTest::
165 UpdateBridgeEnabledTypesOnSyncThread, 97 UpdateEnabledTypesOnSyncThread,
166 base::Unretained(this), 98 base::Unretained(this),
167 enabled_types))); 99 enabled_types)));
168 BlockForSyncThread(); 100 BlockForSyncThread();
169 } 101 }
170 102
171 void TriggerRefreshNotification( 103 void TriggerRefreshNotification(
172 int type, 104 int type,
173 const syncer::ModelTypeStateMap& state_map) { 105 const syncer::ModelTypeStateMap& state_map) {
174 content::NotificationService::current()->Notify( 106 content::NotificationService::current()->Notify(
175 type, 107 type,
176 content::Source<Profile>(&mock_profile_), 108 content::Source<Profile>(&mock_profile_),
177 content::Details<const syncer::ModelTypeStateMap>(&state_map)); 109 content::Details<const syncer::ModelTypeStateMap>(&state_map));
110 BlockForSyncThread();
178 } 111 }
179 112
180 private: 113 private:
181 void VerifyAndDestroyObserverOnSyncThread() { 114 void VerifyAndDestroyObserverOnSyncThread(
115 const syncer::ModelTypeStateMap& expected_states,
116 syncer::IncomingNotificationSource expected_source) {
182 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); 117 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
183 if (!sync_handler_) { 118 if (sync_handler_.get()) {
184 sync_handler_notification_failure_ = true; 119 sync_handler_notification_success_ =
120 (sync_handler_->GetNotificationCount() == 1) &&
121 ObjectIdStateMapEquals(
122 sync_handler_->GetLastNotificationIdStateMap(),
123 syncer::ModelTypeStateMapToObjectIdStateMap(expected_states)) &&
124 (sync_handler_->GetLastNotificationSource() == expected_source);
125 bridge_->UnregisterHandler(sync_handler_.get());
185 } else { 126 } else {
186 sync_handler_notification_failure_ = 127 sync_handler_notification_success_ = false;
187 !sync_handler_->ReceivedProperNotification();
188 delete sync_handler_;
189 sync_handler_ = NULL;
190 } 128 }
129 sync_handler_.reset();
191 } 130 }
192 131
193 void CreateObserverOnSyncThread( 132 void CreateObserverOnSyncThread() {
194 const syncer::ObjectIdStateMap& expected_states,
195 syncer::IncomingNotificationSource expected_source) {
196 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); 133 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
197 sync_handler_ = new FakeInvalidationHandler( 134 sync_handler_.reset(new syncer::FakeInvalidationHandler());
198 sync_thread_.message_loop_proxy(), 135 bridge_->RegisterHandler(sync_handler_.get());
199 bridge_.get(),
200 expected_states,
201 expected_source);
202 } 136 }
203 137
204 void UpdateBridgeEnabledTypesOnSyncThread( 138 void UpdateEnabledTypesOnSyncThread(
205 syncer::ModelTypeSet enabled_types) { 139 syncer::ModelTypeSet enabled_types) {
206 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); 140 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
207 bridge_->UpdateEnabledTypes(enabled_types); 141 bridge_->UpdateRegisteredIds(
208 } 142 sync_handler_.get(), ModelTypeSetToObjectIdSet(enabled_types));
209
210 void SignalOnSyncThread() {
211 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
212 done_.Signal();
213 } 143 }
214 144
215 void BlockForSyncThread() { 145 void BlockForSyncThread() {
216 done_.Reset(); 146 // Post a task to the sync thread's message loop and block until
217 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( 147 // it runs.
148 base::RunLoop run_loop;
149 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTaskAndReply(
218 FROM_HERE, 150 FROM_HERE,
219 base::Bind(&ChromeSyncNotificationBridgeTest::SignalOnSyncThread, 151 base::Bind(&DoNothing),
220 base::Unretained(this)))); 152 run_loop.QuitClosure()));
221 done_.TimedWait(TestTimeouts::action_timeout()); 153 run_loop.Run();
222 if (!done_.IsSignaled())
223 ADD_FAILURE() << "Timed out waiting for sync thread.";
224 } 154 }
225 155
156 MessageLoop ui_loop_;
226 content::TestBrowserThread ui_thread_; 157 content::TestBrowserThread ui_thread_;
227 base::Thread sync_thread_; 158 base::Thread sync_thread_;
228 NiceMock<ProfileMock> mock_profile_; 159 NiceMock<ProfileMock> mock_profile_;
229 // Created/used/destroyed on sync thread. 160 // Created/used/destroyed on sync thread.
230 FakeInvalidationHandler* sync_handler_; 161 scoped_ptr<syncer::FakeInvalidationHandler> sync_handler_;
231 bool sync_handler_notification_failure_; 162 bool sync_handler_notification_success_;
232 scoped_ptr<ChromeSyncNotificationBridge> bridge_; 163 scoped_ptr<ChromeSyncNotificationBridge> bridge_;
233 base::WaitableEvent done_;
234 }; 164 };
235 165
236 // Adds an observer on the sync thread, triggers a local refresh 166 // Adds an observer on the sync thread, triggers a local refresh
237 // notification, and ensures the bridge posts a LOCAL_NOTIFICATION 167 // notification, and ensures the bridge posts a LOCAL_NOTIFICATION
238 // with the proper state to it. 168 // with the proper state to it.
239 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotification) { 169 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotification) {
240 syncer::ModelTypeStateMap state_map; 170 syncer::ModelTypeStateMap state_map;
241 state_map.insert( 171 state_map.insert(
242 std::make_pair(syncer::SESSIONS, syncer::InvalidationState())); 172 std::make_pair(syncer::SESSIONS, syncer::InvalidationState()));
243 CreateObserverWithExpectations(state_map, syncer::LOCAL_NOTIFICATION); 173 CreateObserver();
174 UpdateEnabledTypes(syncer::ModelTypeSet(syncer::SESSIONS));
244 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, 175 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
245 state_map); 176 state_map);
246 VerifyAndDestroyObserver(); 177 VerifyAndDestroyObserver(state_map, syncer::LOCAL_NOTIFICATION);
247 } 178 }
248 179
249 // Adds an observer on the sync thread, triggers a remote refresh 180 // Adds an observer on the sync thread, triggers a remote refresh
250 // notification, and ensures the bridge posts a REMOTE_NOTIFICATION 181 // notification, and ensures the bridge posts a REMOTE_NOTIFICATION
251 // with the proper state to it. 182 // with the proper state to it.
252 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotification) { 183 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotification) {
253 syncer::ModelTypeStateMap state_map; 184 syncer::ModelTypeStateMap state_map;
254 state_map.insert( 185 state_map.insert(
255 std::make_pair(syncer::SESSIONS, syncer::InvalidationState())); 186 std::make_pair(syncer::SESSIONS, syncer::InvalidationState()));
256 CreateObserverWithExpectations(state_map, syncer::REMOTE_NOTIFICATION); 187 CreateObserver();
188 UpdateEnabledTypes(syncer::ModelTypeSet(syncer::SESSIONS));
257 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, 189 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
258 state_map); 190 state_map);
259 VerifyAndDestroyObserver(); 191 VerifyAndDestroyObserver(state_map, syncer::REMOTE_NOTIFICATION);
260 } 192 }
261 193
262 // Adds an observer on the sync thread, triggers a local refresh 194 // Adds an observer on the sync thread, triggers a local refresh
263 // notification with empty state map and ensures the bridge posts a 195 // notification with empty state map and ensures the bridge posts a
264 // LOCAL_NOTIFICATION with the proper state to it. 196 // LOCAL_NOTIFICATION with the proper state to it.
265 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotificationEmptyPayloadMap) { 197 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotificationEmptyPayloadMap) {
266 const syncer::ModelTypeSet enabled_types( 198 const syncer::ModelTypeSet enabled_types(
267 syncer::BOOKMARKS, syncer::PASSWORDS); 199 syncer::BOOKMARKS, syncer::PASSWORDS);
268 const syncer::ModelTypeStateMap enabled_types_state_map = 200 const syncer::ModelTypeStateMap enabled_types_state_map =
269 syncer::ModelTypeSetToStateMap(enabled_types, std::string()); 201 syncer::ModelTypeSetToStateMap(enabled_types, std::string());
270 CreateObserverWithExpectations( 202 CreateObserver();
271 enabled_types_state_map, syncer::LOCAL_NOTIFICATION); 203 UpdateEnabledTypes(enabled_types);
272 UpdateBridgeEnabledTypes(enabled_types);
273 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, 204 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
274 syncer::ModelTypeStateMap()); 205 syncer::ModelTypeStateMap());
275 VerifyAndDestroyObserver(); 206 VerifyAndDestroyObserver(
207 enabled_types_state_map, syncer::LOCAL_NOTIFICATION);
276 } 208 }
277 209
278 // Adds an observer on the sync thread, triggers a remote refresh 210 // Adds an observer on the sync thread, triggers a remote refresh
279 // notification with empty state map and ensures the bridge posts a 211 // notification with empty state map and ensures the bridge posts a
280 // REMOTE_NOTIFICATION with the proper state to it. 212 // REMOTE_NOTIFICATION with the proper state to it.
281 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotificationEmptyPayloadMap) { 213 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotificationEmptyPayloadMap) {
282 const syncer::ModelTypeSet enabled_types( 214 const syncer::ModelTypeSet enabled_types(
283 syncer::BOOKMARKS, syncer::TYPED_URLS); 215 syncer::BOOKMARKS, syncer::TYPED_URLS);
284 const syncer::ModelTypeStateMap enabled_types_state_map = 216 const syncer::ModelTypeStateMap enabled_types_state_map =
285 syncer::ModelTypeSetToStateMap(enabled_types, std::string()); 217 syncer::ModelTypeSetToStateMap(enabled_types, std::string());
286 CreateObserverWithExpectations( 218 CreateObserver();
287 enabled_types_state_map, syncer::REMOTE_NOTIFICATION); 219 UpdateEnabledTypes(enabled_types);
288 UpdateBridgeEnabledTypes(enabled_types);
289 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, 220 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
290 syncer::ModelTypeStateMap()); 221 syncer::ModelTypeStateMap());
291 VerifyAndDestroyObserver(); 222 VerifyAndDestroyObserver(
223 enabled_types_state_map, syncer::REMOTE_NOTIFICATION);
292 } 224 }
293 225
294 } // namespace 226 } // namespace
295 } // namespace browser_sync 227 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698