OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "sync/notifier/p2p_invalidator.h" | |
6 | |
7 #include <cstddef> | |
8 | |
9 #include "jingle/notifier/listener/fake_push_client.h" | |
10 #include "sync/internal_api/public/base/model_type.h" | |
11 #include "sync/notifier/fake_invalidation_handler.h" | |
12 #include "sync/notifier/invalidator_test_template.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 namespace syncer { | |
16 | |
17 namespace { | |
18 | |
19 class P2PInvalidatorTestDelegate { | |
20 public: | |
21 P2PInvalidatorTestDelegate() : fake_push_client_(NULL) {} | |
22 | |
23 ~P2PInvalidatorTestDelegate() { | |
24 DestroyInvalidator(); | |
25 } | |
26 | |
27 void CreateInvalidator( | |
28 const std::string& invalidator_client_id, | |
29 const std::string& initial_state, | |
30 const base::WeakPtr<InvalidationStateTracker>& | |
31 invalidation_state_tracker) { | |
32 DCHECK(!fake_push_client_); | |
33 DCHECK(!invalidator_.get()); | |
34 fake_push_client_ = new notifier::FakePushClient(); | |
35 invalidator_.reset( | |
36 new P2PInvalidator( | |
37 scoped_ptr<notifier::PushClient>(fake_push_client_), | |
38 invalidator_client_id, | |
39 NOTIFY_OTHERS)); | |
40 } | |
41 | |
42 P2PInvalidator* GetInvalidator() { | |
43 return invalidator_.get(); | |
44 } | |
45 | |
46 notifier::FakePushClient* GetPushClient() { | |
47 return fake_push_client_; | |
48 } | |
49 | |
50 void DestroyInvalidator() { | |
51 invalidator_.reset(); | |
52 fake_push_client_ = NULL; | |
53 } | |
54 | |
55 void WaitForInvalidator() { | |
56 // Do Nothing. | |
57 } | |
58 | |
59 void TriggerOnInvalidatorStateChange(InvalidatorState state) { | |
60 if (state == INVALIDATIONS_ENABLED) { | |
61 fake_push_client_->EnableNotifications(); | |
62 } else { | |
63 fake_push_client_->DisableNotifications(ToNotifierReasonForTest(state)); | |
64 } | |
65 } | |
66 | |
67 void TriggerOnIncomingInvalidation( | |
68 const ObjectIdInvalidationMap& invalidation_map) { | |
69 const P2PNotificationData notification_data( | |
70 std::string(), NOTIFY_ALL, invalidation_map); | |
71 notifier::Notification notification; | |
72 notification.channel = kSyncP2PNotificationChannel; | |
73 notification.data = notification_data.ToString(); | |
74 fake_push_client_->SimulateIncomingNotification(notification); | |
75 } | |
76 | |
77 private: | |
78 // Owned by |invalidator_|. | |
79 notifier::FakePushClient* fake_push_client_; | |
80 scoped_ptr<P2PInvalidator> invalidator_; | |
81 }; | |
82 | |
83 class P2PInvalidatorTest : public testing::Test { | |
84 protected: | |
85 P2PInvalidatorTest() | |
86 : next_sent_notification_to_reflect_(0) { | |
87 delegate_.CreateInvalidator("sender", | |
88 "fake_state", | |
89 base::WeakPtr<InvalidationStateTracker>()); | |
90 delegate_.GetInvalidator()->RegisterHandler(&fake_handler_); | |
91 } | |
92 | |
93 virtual ~P2PInvalidatorTest() { | |
94 delegate_.GetInvalidator()->UnregisterHandler(&fake_handler_); | |
95 } | |
96 | |
97 ObjectIdInvalidationMap MakeInvalidationMap(ModelTypeSet types) { | |
98 ObjectIdInvalidationMap invalidations; | |
99 ObjectIdSet ids = ModelTypeSetToObjectIdSet(types); | |
100 return ObjectIdInvalidationMap::InvalidateAll(ids); | |
101 } | |
102 | |
103 // Simulate receiving all the notifications we sent out since last | |
104 // time this was called. | |
105 void ReflectSentNotifications() { | |
106 const std::vector<notifier::Notification>& sent_notifications = | |
107 delegate_.GetPushClient()->sent_notifications(); | |
108 for(size_t i = next_sent_notification_to_reflect_; | |
109 i < sent_notifications.size(); ++i) { | |
110 delegate_.GetInvalidator()->OnIncomingNotification(sent_notifications[i]); | |
111 } | |
112 next_sent_notification_to_reflect_ = sent_notifications.size(); | |
113 } | |
114 | |
115 FakeInvalidationHandler fake_handler_; | |
116 P2PInvalidatorTestDelegate delegate_; | |
117 | |
118 private: | |
119 size_t next_sent_notification_to_reflect_; | |
120 }; | |
121 | |
122 // Make sure the P2PNotificationTarget <-> string conversions work. | |
123 TEST_F(P2PInvalidatorTest, P2PNotificationTarget) { | |
124 for (int i = FIRST_NOTIFICATION_TARGET; | |
125 i <= LAST_NOTIFICATION_TARGET; ++i) { | |
126 P2PNotificationTarget target = static_cast<P2PNotificationTarget>(i); | |
127 const std::string& target_str = P2PNotificationTargetToString(target); | |
128 EXPECT_FALSE(target_str.empty()); | |
129 EXPECT_EQ(target, P2PNotificationTargetFromString(target_str)); | |
130 } | |
131 EXPECT_EQ(NOTIFY_SELF, P2PNotificationTargetFromString("unknown")); | |
132 } | |
133 | |
134 // Make sure notification targeting works correctly. | |
135 TEST_F(P2PInvalidatorTest, P2PNotificationDataIsTargeted) { | |
136 { | |
137 const P2PNotificationData notification_data( | |
138 "sender", NOTIFY_SELF, ObjectIdInvalidationMap()); | |
139 EXPECT_TRUE(notification_data.IsTargeted("sender")); | |
140 EXPECT_FALSE(notification_data.IsTargeted("other1")); | |
141 EXPECT_FALSE(notification_data.IsTargeted("other2")); | |
142 } | |
143 { | |
144 const P2PNotificationData notification_data( | |
145 "sender", NOTIFY_OTHERS, ObjectIdInvalidationMap()); | |
146 EXPECT_FALSE(notification_data.IsTargeted("sender")); | |
147 EXPECT_TRUE(notification_data.IsTargeted("other1")); | |
148 EXPECT_TRUE(notification_data.IsTargeted("other2")); | |
149 } | |
150 { | |
151 const P2PNotificationData notification_data( | |
152 "sender", NOTIFY_ALL, ObjectIdInvalidationMap()); | |
153 EXPECT_TRUE(notification_data.IsTargeted("sender")); | |
154 EXPECT_TRUE(notification_data.IsTargeted("other1")); | |
155 EXPECT_TRUE(notification_data.IsTargeted("other2")); | |
156 } | |
157 } | |
158 | |
159 // Make sure the P2PNotificationData <-> string conversions work for a | |
160 // default-constructed P2PNotificationData. | |
161 TEST_F(P2PInvalidatorTest, P2PNotificationDataDefault) { | |
162 const P2PNotificationData notification_data; | |
163 EXPECT_TRUE(notification_data.IsTargeted(std::string())); | |
164 EXPECT_FALSE(notification_data.IsTargeted("other1")); | |
165 EXPECT_FALSE(notification_data.IsTargeted("other2")); | |
166 EXPECT_TRUE(notification_data.GetIdInvalidationMap().Empty()); | |
167 const std::string& notification_data_str = notification_data.ToString(); | |
168 EXPECT_EQ( | |
169 "{\"invalidations\":[],\"notificationType\":\"notifySelf\"," | |
170 "\"senderId\":\"\"}", notification_data_str); | |
171 | |
172 P2PNotificationData notification_data_parsed; | |
173 EXPECT_TRUE(notification_data_parsed.ResetFromString(notification_data_str)); | |
174 EXPECT_TRUE(notification_data.Equals(notification_data_parsed)); | |
175 } | |
176 | |
177 // Make sure the P2PNotificationData <-> string conversions work for a | |
178 // non-default-constructed P2PNotificationData. | |
179 TEST_F(P2PInvalidatorTest, P2PNotificationDataNonDefault) { | |
180 ObjectIdInvalidationMap invalidation_map = | |
181 ObjectIdInvalidationMap::InvalidateAll( | |
182 ModelTypeSetToObjectIdSet(ModelTypeSet(BOOKMARKS, THEMES))); | |
183 const P2PNotificationData notification_data("sender", | |
184 NOTIFY_ALL, | |
185 invalidation_map); | |
186 EXPECT_TRUE(notification_data.IsTargeted("sender")); | |
187 EXPECT_TRUE(notification_data.IsTargeted("other1")); | |
188 EXPECT_TRUE(notification_data.IsTargeted("other2")); | |
189 EXPECT_EQ(invalidation_map, notification_data.GetIdInvalidationMap()); | |
190 const std::string& notification_data_str = notification_data.ToString(); | |
191 EXPECT_EQ( | |
192 "{\"invalidations\":[" | |
193 "{\"isUnknownVersion\":true," | |
194 "\"objectId\":{\"name\":\"BOOKMARK\",\"source\":1004}}," | |
195 "{\"isUnknownVersion\":true," | |
196 "\"objectId\":{\"name\":\"THEME\",\"source\":1004}}" | |
197 "],\"notificationType\":\"notifyAll\"," | |
198 "\"senderId\":\"sender\"}", notification_data_str); | |
199 | |
200 P2PNotificationData notification_data_parsed; | |
201 EXPECT_TRUE(notification_data_parsed.ResetFromString(notification_data_str)); | |
202 EXPECT_TRUE(notification_data.Equals(notification_data_parsed)); | |
203 } | |
204 | |
205 // Set up the P2PInvalidator, simulate a successful connection, and send | |
206 // a notification with the default target (NOTIFY_OTHERS). The | |
207 // observer should receive only a notification from the call to | |
208 // UpdateEnabledTypes(). | |
209 TEST_F(P2PInvalidatorTest, NotificationsBasic) { | |
210 const ModelTypeSet enabled_types(BOOKMARKS, PREFERENCES); | |
211 | |
212 P2PInvalidator* const invalidator = delegate_.GetInvalidator(); | |
213 notifier::FakePushClient* const push_client = delegate_.GetPushClient(); | |
214 | |
215 invalidator->UpdateRegisteredIds(&fake_handler_, | |
216 ModelTypeSetToObjectIdSet(enabled_types)); | |
217 | |
218 const char kEmail[] = "foo@bar.com"; | |
219 const char kToken[] = "token"; | |
220 invalidator->UpdateCredentials(kEmail, kToken); | |
221 { | |
222 notifier::Subscription expected_subscription; | |
223 expected_subscription.channel = kSyncP2PNotificationChannel; | |
224 expected_subscription.from = kEmail; | |
225 EXPECT_TRUE(notifier::SubscriptionListsEqual( | |
226 push_client->subscriptions(), | |
227 notifier::SubscriptionList(1, expected_subscription))); | |
228 } | |
229 EXPECT_EQ(kEmail, push_client->email()); | |
230 EXPECT_EQ(kToken, push_client->token()); | |
231 | |
232 ReflectSentNotifications(); | |
233 push_client->EnableNotifications(); | |
234 EXPECT_EQ(INVALIDATIONS_ENABLED, fake_handler_.GetInvalidatorState()); | |
235 | |
236 ReflectSentNotifications(); | |
237 EXPECT_EQ(1, fake_handler_.GetInvalidationCount()); | |
238 EXPECT_THAT( | |
239 MakeInvalidationMap(enabled_types), | |
240 Eq(fake_handler_.GetLastInvalidationMap())); | |
241 | |
242 // Sent with target NOTIFY_OTHERS so should not be propagated to | |
243 // |fake_handler_|. | |
244 invalidator->SendInvalidation( | |
245 ModelTypeSetToObjectIdSet(ModelTypeSet(THEMES, APPS))); | |
246 | |
247 ReflectSentNotifications(); | |
248 EXPECT_EQ(1, fake_handler_.GetInvalidationCount()); | |
249 } | |
250 | |
251 // Set up the P2PInvalidator and send out notifications with various | |
252 // target settings. The notifications received by the observer should | |
253 // be consistent with the target settings. | |
254 TEST_F(P2PInvalidatorTest, SendNotificationData) { | |
255 const ModelTypeSet enabled_types(BOOKMARKS, PREFERENCES, THEMES); | |
256 const ModelTypeSet changed_types(THEMES, APPS); | |
257 const ModelTypeSet expected_types(THEMES); | |
258 | |
259 const ObjectIdInvalidationMap& invalidation_map = | |
260 MakeInvalidationMap(changed_types); | |
261 | |
262 P2PInvalidator* const invalidator = delegate_.GetInvalidator(); | |
263 notifier::FakePushClient* const push_client = delegate_.GetPushClient(); | |
264 | |
265 invalidator->UpdateRegisteredIds(&fake_handler_, | |
266 ModelTypeSetToObjectIdSet(enabled_types)); | |
267 | |
268 invalidator->UpdateCredentials("foo@bar.com", "fake_token"); | |
269 | |
270 ReflectSentNotifications(); | |
271 push_client->EnableNotifications(); | |
272 EXPECT_EQ(INVALIDATIONS_ENABLED, fake_handler_.GetInvalidatorState()); | |
273 | |
274 ReflectSentNotifications(); | |
275 EXPECT_EQ(1, fake_handler_.GetInvalidationCount()); | |
276 EXPECT_EQ(ModelTypeSetToObjectIdSet(enabled_types), | |
277 fake_handler_.GetLastInvalidationMap().GetObjectIds()); | |
278 | |
279 // Should be dropped. | |
280 invalidator->SendNotificationDataForTest(P2PNotificationData()); | |
281 ReflectSentNotifications(); | |
282 EXPECT_EQ(1, fake_handler_.GetInvalidationCount()); | |
283 | |
284 const ObjectIdSet& expected_ids = ModelTypeSetToObjectIdSet(expected_types); | |
285 | |
286 // Should be propagated. | |
287 invalidator->SendNotificationDataForTest( | |
288 P2PNotificationData("sender", NOTIFY_SELF, invalidation_map)); | |
289 ReflectSentNotifications(); | |
290 EXPECT_EQ(2, fake_handler_.GetInvalidationCount()); | |
291 EXPECT_EQ(expected_ids, | |
292 fake_handler_.GetLastInvalidationMap().GetObjectIds()); | |
293 | |
294 // Should be dropped. | |
295 invalidator->SendNotificationDataForTest( | |
296 P2PNotificationData("sender2", NOTIFY_SELF, invalidation_map)); | |
297 ReflectSentNotifications(); | |
298 EXPECT_EQ(2, fake_handler_.GetInvalidationCount()); | |
299 | |
300 // Should be dropped. | |
301 invalidator->SendNotificationDataForTest( | |
302 P2PNotificationData("sender", NOTIFY_SELF, ObjectIdInvalidationMap())); | |
303 ReflectSentNotifications(); | |
304 EXPECT_EQ(2, fake_handler_.GetInvalidationCount()); | |
305 | |
306 // Should be dropped. | |
307 invalidator->SendNotificationDataForTest( | |
308 P2PNotificationData("sender", NOTIFY_OTHERS, invalidation_map)); | |
309 ReflectSentNotifications(); | |
310 EXPECT_EQ(2, fake_handler_.GetInvalidationCount()); | |
311 | |
312 // Should be propagated. | |
313 invalidator->SendNotificationDataForTest( | |
314 P2PNotificationData("sender2", NOTIFY_OTHERS, invalidation_map)); | |
315 ReflectSentNotifications(); | |
316 EXPECT_EQ(3, fake_handler_.GetInvalidationCount()); | |
317 EXPECT_EQ(expected_ids, | |
318 fake_handler_.GetLastInvalidationMap().GetObjectIds()); | |
319 | |
320 // Should be dropped. | |
321 invalidator->SendNotificationDataForTest( | |
322 P2PNotificationData("sender2", NOTIFY_OTHERS, ObjectIdInvalidationMap())); | |
323 ReflectSentNotifications(); | |
324 EXPECT_EQ(3, fake_handler_.GetInvalidationCount()); | |
325 | |
326 // Should be propagated. | |
327 invalidator->SendNotificationDataForTest( | |
328 P2PNotificationData("sender", NOTIFY_ALL, invalidation_map)); | |
329 ReflectSentNotifications(); | |
330 EXPECT_EQ(4, fake_handler_.GetInvalidationCount()); | |
331 EXPECT_EQ(expected_ids, | |
332 fake_handler_.GetLastInvalidationMap().GetObjectIds()); | |
333 | |
334 // Should be propagated. | |
335 invalidator->SendNotificationDataForTest( | |
336 P2PNotificationData("sender2", NOTIFY_ALL, invalidation_map)); | |
337 ReflectSentNotifications(); | |
338 EXPECT_EQ(5, fake_handler_.GetInvalidationCount()); | |
339 EXPECT_EQ(expected_ids, | |
340 fake_handler_.GetLastInvalidationMap().GetObjectIds()); | |
341 | |
342 // Should be dropped. | |
343 invalidator->SendNotificationDataForTest( | |
344 P2PNotificationData("sender2", NOTIFY_ALL, ObjectIdInvalidationMap())); | |
345 ReflectSentNotifications(); | |
346 EXPECT_EQ(5, fake_handler_.GetInvalidationCount()); | |
347 } | |
348 | |
349 INSTANTIATE_TYPED_TEST_CASE_P( | |
350 P2PInvalidatorTest, InvalidatorTest, | |
351 P2PInvalidatorTestDelegate); | |
352 | |
353 } // namespace | |
354 | |
355 } // namespace syncer | |
OLD | NEW |