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

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 compile 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 use
39 // ModelTypeStateMap. ReceivedProperNotification() will return true only 37 // a fake (vs a mock) so we don't have to worry about possible thread
40 // if the observer has received a notification with the proper source and 38 // safety issues within GTest/GMock.
Nicolas Zea 2012/08/29 23:41:05 I don't think this comment makes sense here anymor
akalin 2012/08/30 22:20:38 Hmm actually I think the general idea belongs here
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_(NULL),
113 sync_handler_notification_failure_(false), 49 sync_handler_notification_success_(false) {}
114 done_(true, false) {}
115 50
116 virtual ~ChromeSyncNotificationBridgeTest() {} 51 virtual ~ChromeSyncNotificationBridgeTest() {}
117 52
118 protected: 53 protected:
119 virtual void SetUp() OVERRIDE { 54 virtual void SetUp() OVERRIDE {
120 ASSERT_TRUE(sync_thread_.Start()); 55 ASSERT_TRUE(sync_thread_.Start());
121 bridge_.reset( 56 bridge_.reset(
122 new ChromeSyncNotificationBridge( 57 new ChromeSyncNotificationBridge(
123 &mock_profile_, sync_thread_.message_loop_proxy())); 58 &mock_profile_, sync_thread_.message_loop_proxy()));
124 } 59 }
125 60
126 virtual void TearDown() OVERRIDE { 61 virtual void TearDown() OVERRIDE {
127 bridge_->StopForShutdown(); 62 bridge_->StopForShutdown();
128 sync_thread_.Stop(); 63 sync_thread_.Stop();
129 // Must be reset only after the sync thread is stopped. 64 // Must be reset only after the sync thread is stopped.
130 bridge_.reset(); 65 bridge_.reset();
131 EXPECT_EQ(NULL, sync_handler_); 66 EXPECT_EQ(NULL, sync_handler_);
132 if (sync_handler_notification_failure_) 67 if (!sync_handler_notification_success_)
133 ADD_FAILURE() << "Sync Observer did not receive proper notification."; 68 ADD_FAILURE() << "Sync handler did not receive proper notification.";
134 } 69 }
135 70
136 void VerifyAndDestroyObserver() { 71 void VerifyAndDestroyObserver(
72 const syncer::ModelTypeStateMap& expected_states,
73 syncer::IncomingNotificationSource expected_source) {
137 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( 74 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
138 FROM_HERE, 75 FROM_HERE,
139 base::Bind(&ChromeSyncNotificationBridgeTest:: 76 base::Bind(&ChromeSyncNotificationBridgeTest::
140 VerifyAndDestroyObserverOnSyncThread, 77 VerifyAndDestroyObserverOnSyncThread,
141 base::Unretained(this)))); 78 base::Unretained(this),
79 expected_states,
80 expected_source)));
142 BlockForSyncThread(); 81 BlockForSyncThread();
143 } 82 }
144 83
145 void CreateObserverWithExpectations( 84 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( 85 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
151 FROM_HERE, 86 FROM_HERE,
152 base::Bind( 87 base::Bind(
153 &ChromeSyncNotificationBridgeTest::CreateObserverOnSyncThread, 88 &ChromeSyncNotificationBridgeTest::CreateObserverOnSyncThread,
154 base::Unretained(this), 89 base::Unretained(this))));
155 expected_id_state_map,
156 expected_source)));
157 BlockForSyncThread(); 90 BlockForSyncThread();
158 } 91 }
159 92
160 void UpdateBridgeEnabledTypes(syncer::ModelTypeSet enabled_types) { 93 void UpdateEnabledTypes(syncer::ModelTypeSet enabled_types) {
161 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( 94 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
162 FROM_HERE, 95 FROM_HERE,
163 base::Bind( 96 base::Bind(
164 &ChromeSyncNotificationBridgeTest:: 97 &ChromeSyncNotificationBridgeTest::
165 UpdateBridgeEnabledTypesOnSyncThread, 98 UpdateEnabledTypesOnSyncThread,
166 base::Unretained(this), 99 base::Unretained(this),
167 enabled_types))); 100 enabled_types)));
168 BlockForSyncThread(); 101 BlockForSyncThread();
169 } 102 }
170 103
171 void TriggerRefreshNotification( 104 void TriggerRefreshNotification(
172 int type, 105 int type,
173 const syncer::ModelTypeStateMap& state_map) { 106 const syncer::ModelTypeStateMap& state_map) {
174 content::NotificationService::current()->Notify( 107 content::NotificationService::current()->Notify(
175 type, 108 type,
176 content::Source<Profile>(&mock_profile_), 109 content::Source<Profile>(&mock_profile_),
177 content::Details<const syncer::ModelTypeStateMap>(&state_map)); 110 content::Details<const syncer::ModelTypeStateMap>(&state_map));
111 BlockForSyncThread();
178 } 112 }
179 113
180 private: 114 private:
181 void VerifyAndDestroyObserverOnSyncThread() { 115 void VerifyAndDestroyObserverOnSyncThread(
116 const syncer::ModelTypeStateMap& expected_states,
117 syncer::IncomingNotificationSource expected_source) {
182 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); 118 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
183 if (!sync_handler_) { 119 if (sync_handler_) {
184 sync_handler_notification_failure_ = true; 120 sync_handler_notification_success_ =
121 (sync_handler_->GetNotificationCount() == 1) &&
122 ObjectIdStateMapEquals(
123 sync_handler_->GetLastNotificationIdStateMap(),
124 syncer::ModelTypeStateMapToObjectIdStateMap(expected_states)) &&
125 (sync_handler_->GetLastNotificationSource() == expected_source);
126 bridge_->UnregisterHandler(sync_handler_);
185 } else { 127 } else {
186 sync_handler_notification_failure_ = 128 sync_handler_notification_success_ = false;
187 !sync_handler_->ReceivedProperNotification();
188 delete sync_handler_;
189 sync_handler_ = NULL;
190 } 129 }
130 delete sync_handler_;
Nicolas Zea 2012/08/29 23:41:05 make sync_handler_ a scoped_ptr?
akalin 2012/08/30 22:20:38 Done.
131 sync_handler_ = NULL;
191 } 132 }
192 133
193 void CreateObserverOnSyncThread( 134 void CreateObserverOnSyncThread() {
194 const syncer::ObjectIdStateMap& expected_states,
195 syncer::IncomingNotificationSource expected_source) {
196 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); 135 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
197 sync_handler_ = new FakeInvalidationHandler( 136 sync_handler_ = new syncer::FakeInvalidationHandler();
198 sync_thread_.message_loop_proxy(), 137 bridge_->RegisterHandler(sync_handler_);
199 bridge_.get(),
200 expected_states,
201 expected_source);
202 } 138 }
203 139
204 void UpdateBridgeEnabledTypesOnSyncThread( 140 void UpdateEnabledTypesOnSyncThread(
205 syncer::ModelTypeSet enabled_types) { 141 syncer::ModelTypeSet enabled_types) {
206 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); 142 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
207 bridge_->UpdateEnabledTypes(enabled_types); 143 bridge_->UpdateRegisteredIds(
208 } 144 sync_handler_, ModelTypeSetToObjectIdSet(enabled_types));
209
210 void SignalOnSyncThread() {
211 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
212 done_.Signal();
213 } 145 }
214 146
215 void BlockForSyncThread() { 147 void BlockForSyncThread() {
216 done_.Reset(); 148 // Post a task to the sync thread's message loop and block until
217 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( 149 // it runs.
150 base::RunLoop run_loop;
151 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTaskAndReply(
218 FROM_HERE, 152 FROM_HERE,
219 base::Bind(&ChromeSyncNotificationBridgeTest::SignalOnSyncThread, 153 base::Bind(&DoNothing),
220 base::Unretained(this)))); 154 run_loop.QuitClosure()));
Nicolas Zea 2012/08/29 23:41:05 don't you need to do run_loop.run()?
akalin 2012/08/30 22:20:38 Done.
221 done_.TimedWait(TestTimeouts::action_timeout());
222 if (!done_.IsSignaled())
223 ADD_FAILURE() << "Timed out waiting for sync thread.";
224 } 155 }
225 156
157 MessageLoop ui_loop_;
226 content::TestBrowserThread ui_thread_; 158 content::TestBrowserThread ui_thread_;
227 base::Thread sync_thread_; 159 base::Thread sync_thread_;
228 NiceMock<ProfileMock> mock_profile_; 160 NiceMock<ProfileMock> mock_profile_;
229 // Created/used/destroyed on sync thread. 161 // Created/used/destroyed on sync thread.
230 FakeInvalidationHandler* sync_handler_; 162 syncer::FakeInvalidationHandler* sync_handler_;
231 bool sync_handler_notification_failure_; 163 bool sync_handler_notification_success_;
232 scoped_ptr<ChromeSyncNotificationBridge> bridge_; 164 scoped_ptr<ChromeSyncNotificationBridge> bridge_;
233 base::WaitableEvent done_;
234 }; 165 };
235 166
236 // Adds an observer on the sync thread, triggers a local refresh 167 // Adds an observer on the sync thread, triggers a local refresh
237 // notification, and ensures the bridge posts a LOCAL_NOTIFICATION 168 // notification, and ensures the bridge posts a LOCAL_NOTIFICATION
238 // with the proper state to it. 169 // with the proper state to it.
239 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotification) { 170 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotification) {
240 syncer::ModelTypeStateMap state_map; 171 syncer::ModelTypeStateMap state_map;
241 state_map.insert( 172 state_map.insert(
242 std::make_pair(syncer::SESSIONS, syncer::InvalidationState())); 173 std::make_pair(syncer::SESSIONS, syncer::InvalidationState()));
243 CreateObserverWithExpectations(state_map, syncer::LOCAL_NOTIFICATION); 174 CreateObserver();
175 UpdateEnabledTypes(syncer::ModelTypeSet(syncer::SESSIONS));
244 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, 176 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
245 state_map); 177 state_map);
246 VerifyAndDestroyObserver(); 178 VerifyAndDestroyObserver(state_map, syncer::LOCAL_NOTIFICATION);
247 } 179 }
248 180
249 // Adds an observer on the sync thread, triggers a remote refresh 181 // Adds an observer on the sync thread, triggers a remote refresh
250 // notification, and ensures the bridge posts a REMOTE_NOTIFICATION 182 // notification, and ensures the bridge posts a REMOTE_NOTIFICATION
251 // with the proper state to it. 183 // with the proper state to it.
252 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotification) { 184 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotification) {
253 syncer::ModelTypeStateMap state_map; 185 syncer::ModelTypeStateMap state_map;
254 state_map.insert( 186 state_map.insert(
255 std::make_pair(syncer::SESSIONS, syncer::InvalidationState())); 187 std::make_pair(syncer::SESSIONS, syncer::InvalidationState()));
256 CreateObserverWithExpectations(state_map, syncer::REMOTE_NOTIFICATION); 188 CreateObserver();
189 UpdateEnabledTypes(syncer::ModelTypeSet(syncer::SESSIONS));
257 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, 190 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
258 state_map); 191 state_map);
259 VerifyAndDestroyObserver(); 192 VerifyAndDestroyObserver(state_map, syncer::REMOTE_NOTIFICATION);
260 } 193 }
261 194
262 // Adds an observer on the sync thread, triggers a local refresh 195 // Adds an observer on the sync thread, triggers a local refresh
263 // notification with empty state map and ensures the bridge posts a 196 // notification with empty state map and ensures the bridge posts a
264 // LOCAL_NOTIFICATION with the proper state to it. 197 // LOCAL_NOTIFICATION with the proper state to it.
265 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotificationEmptyPayloadMap) { 198 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotificationEmptyPayloadMap) {
266 const syncer::ModelTypeSet enabled_types( 199 const syncer::ModelTypeSet enabled_types(
267 syncer::BOOKMARKS, syncer::PASSWORDS); 200 syncer::BOOKMARKS, syncer::PASSWORDS);
268 const syncer::ModelTypeStateMap enabled_types_state_map = 201 const syncer::ModelTypeStateMap enabled_types_state_map =
269 syncer::ModelTypeSetToStateMap(enabled_types, std::string()); 202 syncer::ModelTypeSetToStateMap(enabled_types, std::string());
270 CreateObserverWithExpectations( 203 CreateObserver();
271 enabled_types_state_map, syncer::LOCAL_NOTIFICATION); 204 UpdateEnabledTypes(enabled_types);
272 UpdateBridgeEnabledTypes(enabled_types);
273 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, 205 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
274 syncer::ModelTypeStateMap()); 206 syncer::ModelTypeStateMap());
275 VerifyAndDestroyObserver(); 207 VerifyAndDestroyObserver(
208 enabled_types_state_map, syncer::LOCAL_NOTIFICATION);
276 } 209 }
277 210
278 // Adds an observer on the sync thread, triggers a remote refresh 211 // Adds an observer on the sync thread, triggers a remote refresh
279 // notification with empty state map and ensures the bridge posts a 212 // notification with empty state map and ensures the bridge posts a
280 // REMOTE_NOTIFICATION with the proper state to it. 213 // REMOTE_NOTIFICATION with the proper state to it.
281 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotificationEmptyPayloadMap) { 214 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotificationEmptyPayloadMap) {
282 const syncer::ModelTypeSet enabled_types( 215 const syncer::ModelTypeSet enabled_types(
283 syncer::BOOKMARKS, syncer::TYPED_URLS); 216 syncer::BOOKMARKS, syncer::TYPED_URLS);
284 const syncer::ModelTypeStateMap enabled_types_state_map = 217 const syncer::ModelTypeStateMap enabled_types_state_map =
285 syncer::ModelTypeSetToStateMap(enabled_types, std::string()); 218 syncer::ModelTypeSetToStateMap(enabled_types, std::string());
286 CreateObserverWithExpectations( 219 CreateObserver();
287 enabled_types_state_map, syncer::REMOTE_NOTIFICATION); 220 UpdateEnabledTypes(enabled_types);
288 UpdateBridgeEnabledTypes(enabled_types);
289 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, 221 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
290 syncer::ModelTypeStateMap()); 222 syncer::ModelTypeStateMap());
291 VerifyAndDestroyObserver(); 223 VerifyAndDestroyObserver(
224 enabled_types_state_map, syncer::REMOTE_NOTIFICATION);
292 } 225 }
293 226
294 } // namespace 227 } // namespace
295 } // namespace browser_sync 228 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698