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.
5 #include "components/invalidation/p2p_invalidator.h"
9 #include "components/invalidation/fake_invalidation_handler.h"
10 #include "components/invalidation/invalidator_state.h"
11 #include "components/invalidation/invalidator_test_template.h"
12 #include "components/invalidation/notifier_reason_util.h"
13 #include "jingle/notifier/listener/fake_push_client.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 class P2PInvalidatorTestDelegate
{
22 P2PInvalidatorTestDelegate() : fake_push_client_(NULL
) {}
24 ~P2PInvalidatorTestDelegate() {
28 void CreateInvalidator(
29 const std::string
& invalidator_client_id
,
30 const std::string
& initial_state
,
31 const base::WeakPtr
<InvalidationStateTracker
>&
32 invalidation_state_tracker
) {
33 DCHECK(!fake_push_client_
);
34 DCHECK(!invalidator_
.get());
35 fake_push_client_
= new notifier::FakePushClient();
38 scoped_ptr
<notifier::PushClient
>(fake_push_client_
),
39 invalidator_client_id
,
43 P2PInvalidator
* GetInvalidator() {
44 return invalidator_
.get();
47 notifier::FakePushClient
* GetPushClient() {
48 return fake_push_client_
;
51 void DestroyInvalidator() {
53 fake_push_client_
= NULL
;
56 void WaitForInvalidator() {
60 void TriggerOnInvalidatorStateChange(InvalidatorState state
) {
61 if (state
== INVALIDATIONS_ENABLED
) {
62 fake_push_client_
->EnableNotifications();
64 fake_push_client_
->DisableNotifications(ToNotifierReasonForTest(state
));
68 void TriggerOnIncomingInvalidation(
69 const ObjectIdInvalidationMap
& invalidation_map
) {
70 const P2PNotificationData
notification_data(
71 std::string(), NOTIFY_ALL
, invalidation_map
);
72 notifier::Notification notification
;
73 notification
.channel
= kSyncP2PNotificationChannel
;
74 notification
.data
= notification_data
.ToString();
75 fake_push_client_
->SimulateIncomingNotification(notification
);
79 // Owned by |invalidator_|.
80 notifier::FakePushClient
* fake_push_client_
;
81 scoped_ptr
<P2PInvalidator
> invalidator_
;
84 class P2PInvalidatorTest
: public testing::Test
{
87 : next_sent_notification_to_reflect_(0) {
88 default_enabled_ids_
.insert(invalidation::ObjectId(10, "A"));
89 default_enabled_ids_
.insert(invalidation::ObjectId(10, "B"));
90 delegate_
.CreateInvalidator("sender",
92 base::WeakPtr
<InvalidationStateTracker
>());
93 delegate_
.GetInvalidator()->RegisterHandler(&fake_handler_
);
96 ~P2PInvalidatorTest() override
{
97 delegate_
.GetInvalidator()->UnregisterHandler(&fake_handler_
);
100 ObjectIdInvalidationMap
MakeInvalidationMap(ObjectIdSet ids
) {
101 return ObjectIdInvalidationMap::InvalidateAll(ids
);
104 // Simulate receiving all the notifications we sent out since last
105 // time this was called.
106 void ReflectSentNotifications() {
107 const std::vector
<notifier::Notification
>& sent_notifications
=
108 delegate_
.GetPushClient()->sent_notifications();
109 for(size_t i
= next_sent_notification_to_reflect_
;
110 i
< sent_notifications
.size(); ++i
) {
111 delegate_
.GetInvalidator()->OnIncomingNotification(sent_notifications
[i
]);
113 next_sent_notification_to_reflect_
= sent_notifications
.size();
116 ObjectIdSet default_enabled_ids_
;
118 FakeInvalidationHandler fake_handler_
;
119 P2PInvalidatorTestDelegate delegate_
;
122 size_t next_sent_notification_to_reflect_
;
125 // Make sure the P2PNotificationTarget <-> string conversions work.
126 TEST_F(P2PInvalidatorTest
, P2PNotificationTarget
) {
127 for (int i
= FIRST_NOTIFICATION_TARGET
;
128 i
<= LAST_NOTIFICATION_TARGET
; ++i
) {
129 P2PNotificationTarget target
= static_cast<P2PNotificationTarget
>(i
);
130 const std::string
& target_str
= P2PNotificationTargetToString(target
);
131 EXPECT_FALSE(target_str
.empty());
132 EXPECT_EQ(target
, P2PNotificationTargetFromString(target_str
));
134 EXPECT_EQ(NOTIFY_SELF
, P2PNotificationTargetFromString("unknown"));
137 // Make sure notification targeting works correctly.
138 TEST_F(P2PInvalidatorTest
, P2PNotificationDataIsTargeted
) {
140 const P2PNotificationData
notification_data(
141 "sender", NOTIFY_SELF
, ObjectIdInvalidationMap());
142 EXPECT_TRUE(notification_data
.IsTargeted("sender"));
143 EXPECT_FALSE(notification_data
.IsTargeted("other1"));
144 EXPECT_FALSE(notification_data
.IsTargeted("other2"));
147 const P2PNotificationData
notification_data(
148 "sender", NOTIFY_OTHERS
, ObjectIdInvalidationMap());
149 EXPECT_FALSE(notification_data
.IsTargeted("sender"));
150 EXPECT_TRUE(notification_data
.IsTargeted("other1"));
151 EXPECT_TRUE(notification_data
.IsTargeted("other2"));
154 const P2PNotificationData
notification_data(
155 "sender", NOTIFY_ALL
, ObjectIdInvalidationMap());
156 EXPECT_TRUE(notification_data
.IsTargeted("sender"));
157 EXPECT_TRUE(notification_data
.IsTargeted("other1"));
158 EXPECT_TRUE(notification_data
.IsTargeted("other2"));
162 // Make sure the P2PNotificationData <-> string conversions work for a
163 // default-constructed P2PNotificationData.
164 TEST_F(P2PInvalidatorTest
, P2PNotificationDataDefault
) {
165 const P2PNotificationData notification_data
;
166 EXPECT_TRUE(notification_data
.IsTargeted(std::string()));
167 EXPECT_FALSE(notification_data
.IsTargeted("other1"));
168 EXPECT_FALSE(notification_data
.IsTargeted("other2"));
169 EXPECT_TRUE(notification_data
.GetIdInvalidationMap().Empty());
170 const std::string
& notification_data_str
= notification_data
.ToString();
172 "{\"invalidations\":[],\"notificationType\":\"notifySelf\","
173 "\"senderId\":\"\"}", notification_data_str
);
175 P2PNotificationData notification_data_parsed
;
176 EXPECT_TRUE(notification_data_parsed
.ResetFromString(notification_data_str
));
177 EXPECT_TRUE(notification_data
.Equals(notification_data_parsed
));
180 // Make sure the P2PNotificationData <-> string conversions work for a
181 // non-default-constructed P2PNotificationData.
182 TEST_F(P2PInvalidatorTest
, P2PNotificationDataNonDefault
) {
183 ObjectIdInvalidationMap invalidation_map
=
184 ObjectIdInvalidationMap::InvalidateAll(default_enabled_ids_
);
185 const P2PNotificationData
notification_data("sender",
188 EXPECT_TRUE(notification_data
.IsTargeted("sender"));
189 EXPECT_TRUE(notification_data
.IsTargeted("other1"));
190 EXPECT_TRUE(notification_data
.IsTargeted("other2"));
191 EXPECT_EQ(invalidation_map
, notification_data
.GetIdInvalidationMap());
192 const std::string
& notification_data_str
= notification_data
.ToString();
194 "{\"invalidations\":["
195 "{\"isUnknownVersion\":true,"
196 "\"objectId\":{\"name\":\"A\",\"source\":10}},"
197 "{\"isUnknownVersion\":true,"
198 "\"objectId\":{\"name\":\"B\",\"source\":10}}"
199 "],\"notificationType\":\"notifyAll\","
200 "\"senderId\":\"sender\"}",
201 notification_data_str
);
203 P2PNotificationData notification_data_parsed
;
204 EXPECT_TRUE(notification_data_parsed
.ResetFromString(notification_data_str
));
205 EXPECT_TRUE(notification_data
.Equals(notification_data_parsed
));
208 // Set up the P2PInvalidator, simulate a successful connection, and send
209 // a notification with the default target (NOTIFY_OTHERS). The
210 // observer should receive only a notification from the call to
211 // UpdateEnabledTypes().
212 TEST_F(P2PInvalidatorTest
, NotificationsBasic
) {
213 P2PInvalidator
* const invalidator
= delegate_
.GetInvalidator();
214 notifier::FakePushClient
* const push_client
= delegate_
.GetPushClient();
216 invalidator
->UpdateRegisteredIds(&fake_handler_
, default_enabled_ids_
);
218 const char kEmail
[] = "foo@bar.com";
219 const char kToken
[] = "token";
220 invalidator
->UpdateCredentials(kEmail
, kToken
);
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
)));
229 EXPECT_EQ(kEmail
, push_client
->email());
230 EXPECT_EQ(kToken
, push_client
->token());
232 ReflectSentNotifications();
233 push_client
->EnableNotifications();
234 EXPECT_EQ(INVALIDATIONS_ENABLED
, fake_handler_
.GetInvalidatorState());
236 ReflectSentNotifications();
237 EXPECT_EQ(1, fake_handler_
.GetInvalidationCount());
238 EXPECT_THAT(MakeInvalidationMap(default_enabled_ids_
),
239 Eq(fake_handler_
.GetLastInvalidationMap()));
241 // Sent with target NOTIFY_OTHERS so should not be propagated to
243 invalidator
->SendInvalidation(default_enabled_ids_
);
245 ReflectSentNotifications();
246 EXPECT_EQ(1, fake_handler_
.GetInvalidationCount());
249 // Set up the P2PInvalidator and send out notifications with various
250 // target settings. The notifications received by the observer should
251 // be consistent with the target settings.
252 TEST_F(P2PInvalidatorTest
, SendNotificationData
) {
253 ObjectIdSet enabled_ids
;
254 ObjectIdSet changed_ids
;
255 ObjectIdSet expected_ids
;
257 enabled_ids
.insert(invalidation::ObjectId(20, "A"));
258 enabled_ids
.insert(invalidation::ObjectId(20, "B"));
259 enabled_ids
.insert(invalidation::ObjectId(20, "C"));
261 changed_ids
.insert(invalidation::ObjectId(20, "A"));
262 changed_ids
.insert(invalidation::ObjectId(20, "Z"));
264 expected_ids
.insert(invalidation::ObjectId(20, "A"));
266 const ObjectIdInvalidationMap
& invalidation_map
=
267 MakeInvalidationMap(changed_ids
);
269 P2PInvalidator
* const invalidator
= delegate_
.GetInvalidator();
270 notifier::FakePushClient
* const push_client
= delegate_
.GetPushClient();
272 invalidator
->UpdateRegisteredIds(&fake_handler_
, enabled_ids
);
274 invalidator
->UpdateCredentials("foo@bar.com", "fake_token");
276 ReflectSentNotifications();
277 push_client
->EnableNotifications();
278 EXPECT_EQ(INVALIDATIONS_ENABLED
, fake_handler_
.GetInvalidatorState());
280 ReflectSentNotifications();
281 EXPECT_EQ(1, fake_handler_
.GetInvalidationCount());
282 EXPECT_EQ(enabled_ids
, fake_handler_
.GetLastInvalidationMap().GetObjectIds());
284 // Should be dropped.
285 invalidator
->SendNotificationDataForTest(P2PNotificationData());
286 ReflectSentNotifications();
287 EXPECT_EQ(1, fake_handler_
.GetInvalidationCount());
289 // Should be propagated.
290 invalidator
->SendNotificationDataForTest(
291 P2PNotificationData("sender", NOTIFY_SELF
, invalidation_map
));
292 ReflectSentNotifications();
293 EXPECT_EQ(2, fake_handler_
.GetInvalidationCount());
294 EXPECT_EQ(expected_ids
,
295 fake_handler_
.GetLastInvalidationMap().GetObjectIds());
297 // Should be dropped.
298 invalidator
->SendNotificationDataForTest(
299 P2PNotificationData("sender2", NOTIFY_SELF
, invalidation_map
));
300 ReflectSentNotifications();
301 EXPECT_EQ(2, fake_handler_
.GetInvalidationCount());
303 // Should be dropped.
304 invalidator
->SendNotificationDataForTest(
305 P2PNotificationData("sender", NOTIFY_SELF
, ObjectIdInvalidationMap()));
306 ReflectSentNotifications();
307 EXPECT_EQ(2, fake_handler_
.GetInvalidationCount());
309 // Should be dropped.
310 invalidator
->SendNotificationDataForTest(
311 P2PNotificationData("sender", NOTIFY_OTHERS
, invalidation_map
));
312 ReflectSentNotifications();
313 EXPECT_EQ(2, fake_handler_
.GetInvalidationCount());
315 // Should be propagated.
316 invalidator
->SendNotificationDataForTest(
317 P2PNotificationData("sender2", NOTIFY_OTHERS
, invalidation_map
));
318 ReflectSentNotifications();
319 EXPECT_EQ(3, fake_handler_
.GetInvalidationCount());
320 EXPECT_EQ(expected_ids
,
321 fake_handler_
.GetLastInvalidationMap().GetObjectIds());
323 // Should be dropped.
324 invalidator
->SendNotificationDataForTest(
325 P2PNotificationData("sender2", NOTIFY_OTHERS
, ObjectIdInvalidationMap()));
326 ReflectSentNotifications();
327 EXPECT_EQ(3, fake_handler_
.GetInvalidationCount());
329 // Should be propagated.
330 invalidator
->SendNotificationDataForTest(
331 P2PNotificationData("sender", NOTIFY_ALL
, invalidation_map
));
332 ReflectSentNotifications();
333 EXPECT_EQ(4, fake_handler_
.GetInvalidationCount());
334 EXPECT_EQ(expected_ids
,
335 fake_handler_
.GetLastInvalidationMap().GetObjectIds());
337 // Should be propagated.
338 invalidator
->SendNotificationDataForTest(
339 P2PNotificationData("sender2", NOTIFY_ALL
, invalidation_map
));
340 ReflectSentNotifications();
341 EXPECT_EQ(5, fake_handler_
.GetInvalidationCount());
342 EXPECT_EQ(expected_ids
,
343 fake_handler_
.GetLastInvalidationMap().GetObjectIds());
345 // Should be dropped.
346 invalidator
->SendNotificationDataForTest(
347 P2PNotificationData("sender2", NOTIFY_ALL
, ObjectIdInvalidationMap()));
348 ReflectSentNotifications();
349 EXPECT_EQ(5, fake_handler_
.GetInvalidationCount());
352 INSTANTIATE_TYPED_TEST_CASE_P(
353 P2PInvalidatorTest
, InvalidatorTest
,
354 P2PInvalidatorTestDelegate
);
358 } // namespace syncer