1 // Copyright 2013 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 "sync/notifier/unacked_invalidation_set.h"
7 #include "base/json/json_string_value_serializer.h"
8 #include "sync/notifier/object_id_invalidation_map.h"
9 #include "sync/notifier/single_object_invalidation_set.h"
10 #include "testing/gmock/include/gmock/gmock-matchers.h"
11 #include "testing/gtest/include/gtest/gtest.h"
15 // Start with some helper functions and classes.
17 using ::testing::MakeMatcher
;
18 using ::testing::MatchResultListener
;
19 using ::testing::Matcher
;
20 using ::testing::MatcherInterface
;
21 using ::testing::PrintToString
;
24 const UnackedInvalidationSet
& invalidations
, ::std::ostream
* os
);
27 const UnackedInvalidationsMap
& map
, ::std::ostream
* os
);
29 ::testing::Matcher
<const UnackedInvalidationSet
&> Eq(
30 const UnackedInvalidationSet
& expected
);
32 ::testing::Matcher
<const UnackedInvalidationsMap
&> Eq(
33 const UnackedInvalidationsMap
& expected
);
35 class UnackedInvalidationSetEqMatcher
36 : public testing::MatcherInterface
<const UnackedInvalidationSet
&> {
38 explicit UnackedInvalidationSetEqMatcher(
39 const UnackedInvalidationSet
& expected
);
41 virtual bool MatchAndExplain(
42 const UnackedInvalidationSet
& actual
,
43 MatchResultListener
* listener
) const OVERRIDE
;
44 virtual void DescribeTo(::std::ostream
* os
) const OVERRIDE
;
45 virtual void DescribeNegationTo(::std::ostream
* os
) const OVERRIDE
;
48 const UnackedInvalidationSet expected_
;
50 DISALLOW_COPY_AND_ASSIGN(UnackedInvalidationSetEqMatcher
);
53 UnackedInvalidationSetEqMatcher::UnackedInvalidationSetEqMatcher(
54 const UnackedInvalidationSet
& expected
)
55 : expected_(expected
) {}
59 struct InvalidationEq
{
60 bool operator()(const syncer::Invalidation
& a
,
61 const syncer::Invalidation
& b
) const {
68 bool UnackedInvalidationSetEqMatcher::MatchAndExplain(
69 const UnackedInvalidationSet
& actual
,
70 MatchResultListener
* listener
) const {
71 // Use our friendship with this class to compare the internals of two
74 // Note that the registration status is intentionally not considered
75 // when performing this comparison.
76 return expected_
.object_id_
== actual
.object_id_
77 && std::equal(expected_
.invalidations_
.begin(),
78 expected_
.invalidations_
.end(),
79 actual
.invalidations_
.begin(),
83 void UnackedInvalidationSetEqMatcher::DescribeTo(::std::ostream
* os
) const {
84 *os
<< " is equal to " << PrintToString(expected_
);
87 void UnackedInvalidationSetEqMatcher::DescribeNegationTo(
88 ::std::ostream
* os
) const {
89 *os
<< " isn't equal to " << PrintToString(expected_
);
94 ObjectIdInvalidationMap
UnackedInvalidationsMapToObjectIdInvalidationMap(
95 const UnackedInvalidationsMap
& state_map
) {
96 ObjectIdInvalidationMap object_id_invalidation_map
;
97 for (UnackedInvalidationsMap::const_iterator it
= state_map
.begin();
98 it
!= state_map
.end(); ++it
) {
99 it
->second
.ExportInvalidations(syncer::WeakHandle
<AckHandler
>(),
100 &object_id_invalidation_map
);
102 return object_id_invalidation_map
;
105 class UnackedInvalidationsMapEqMatcher
106 : public testing::MatcherInterface
<const UnackedInvalidationsMap
&> {
108 explicit UnackedInvalidationsMapEqMatcher(
109 const UnackedInvalidationsMap
& expected
);
111 virtual bool MatchAndExplain(const UnackedInvalidationsMap
& actual
,
112 MatchResultListener
* listener
) const;
113 virtual void DescribeTo(::std::ostream
* os
) const;
114 virtual void DescribeNegationTo(::std::ostream
* os
) const;
117 const UnackedInvalidationsMap expected_
;
119 DISALLOW_COPY_AND_ASSIGN(UnackedInvalidationsMapEqMatcher
);
122 UnackedInvalidationsMapEqMatcher::UnackedInvalidationsMapEqMatcher(
123 const UnackedInvalidationsMap
& expected
)
124 : expected_(expected
) {
127 bool UnackedInvalidationsMapEqMatcher::MatchAndExplain(
128 const UnackedInvalidationsMap
& actual
,
129 MatchResultListener
* listener
) const {
130 ObjectIdInvalidationMap expected_inv
=
131 UnackedInvalidationsMapToObjectIdInvalidationMap(expected_
);
132 ObjectIdInvalidationMap actual_inv
=
133 UnackedInvalidationsMapToObjectIdInvalidationMap(actual
);
135 return expected_inv
== actual_inv
;
138 void UnackedInvalidationsMapEqMatcher::DescribeTo(
139 ::std::ostream
* os
) const {
140 *os
<< " is equal to " << PrintToString(expected_
);
143 void UnackedInvalidationsMapEqMatcher::DescribeNegationTo(
144 ::std::ostream
* os
) const {
145 *os
<< " isn't equal to " << PrintToString(expected_
);
150 void PrintTo(const UnackedInvalidationSet
& invalidations
,
151 ::std::ostream
* os
) {
152 scoped_ptr
<base::DictionaryValue
> value
= invalidations
.ToValue();
155 JSONStringValueSerializer
serializer(&output
);
156 serializer
.set_pretty_print(true);
157 serializer
.Serialize(*value
.get());
162 void PrintTo(const UnackedInvalidationsMap
& map
, ::std::ostream
* os
) {
163 scoped_ptr
<base::ListValue
> list(new base::ListValue
);
164 for (UnackedInvalidationsMap::const_iterator it
= map
.begin();
165 it
!= map
.end(); ++it
) {
166 list
->Append(it
->second
.ToValue().release());
170 JSONStringValueSerializer
serializer(&output
);
171 serializer
.set_pretty_print(true);
172 serializer
.Serialize(*list
.get());
177 Matcher
<const UnackedInvalidationSet
&> Eq(
178 const UnackedInvalidationSet
& expected
) {
179 return MakeMatcher(new UnackedInvalidationSetEqMatcher(expected
));
182 Matcher
<const UnackedInvalidationsMap
&> Eq(
183 const UnackedInvalidationsMap
& expected
) {
184 return MakeMatcher(new UnackedInvalidationsMapEqMatcher(expected
));
187 class UnackedInvalidationSetTest
: public testing::Test
{
189 UnackedInvalidationSetTest()
190 : kObjectId_(10, "ASDF"),
191 unacked_invalidations_(kObjectId_
) {}
193 SingleObjectInvalidationSet
GetStoredInvalidations() {
194 ObjectIdInvalidationMap map
;
195 unacked_invalidations_
.ExportInvalidations(WeakHandle
<AckHandler
>(), &map
);
196 ObjectIdSet ids
= map
.GetObjectIds();
197 if (ids
.find(kObjectId_
) != ids
.end()) {
198 return map
.ForObject(kObjectId_
);
200 return SingleObjectInvalidationSet();
204 const invalidation::ObjectId kObjectId_
;
205 UnackedInvalidationSet unacked_invalidations_
;
210 // Test storage and retrieval of zero invalidations.
211 TEST_F(UnackedInvalidationSetTest
, Empty
) {
212 EXPECT_EQ(0U, GetStoredInvalidations().GetSize());
215 // Test storage and retrieval of a single invalidation.
216 TEST_F(UnackedInvalidationSetTest
, OneInvalidation
) {
217 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
218 unacked_invalidations_
.Add(inv1
);
220 SingleObjectInvalidationSet set
= GetStoredInvalidations();
221 ASSERT_EQ(1U, set
.GetSize());
222 EXPECT_FALSE(set
.StartsWithUnknownVersion());
225 // Test that calling Clear() returns us to the empty state.
226 TEST_F(UnackedInvalidationSetTest
, Clear
) {
227 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
228 unacked_invalidations_
.Add(inv1
);
229 unacked_invalidations_
.Clear();
231 EXPECT_EQ(0U, GetStoredInvalidations().GetSize());
234 // Test that repeated unknown version invalidations are squashed together.
235 TEST_F(UnackedInvalidationSetTest
, UnknownVersions
) {
236 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
237 Invalidation inv2
= Invalidation::InitUnknownVersion(kObjectId_
);
238 Invalidation inv3
= Invalidation::InitUnknownVersion(kObjectId_
);
239 unacked_invalidations_
.Add(inv1
);
240 unacked_invalidations_
.Add(inv2
);
241 unacked_invalidations_
.Add(inv3
);
243 SingleObjectInvalidationSet set
= GetStoredInvalidations();
244 ASSERT_EQ(2U, set
.GetSize());
245 EXPECT_TRUE(set
.StartsWithUnknownVersion());
248 // Tests that no truncation occurs while we're under the limit.
249 TEST_F(UnackedInvalidationSetTest
, NoTruncation
) {
250 size_t kMax
= UnackedInvalidationSet::kMaxBufferedInvalidations
;
252 for (size_t i
= 0; i
< kMax
; ++i
) {
253 Invalidation inv
= Invalidation::Init(kObjectId_
, i
, "payload");
254 unacked_invalidations_
.Add(inv
);
257 SingleObjectInvalidationSet set
= GetStoredInvalidations();
258 ASSERT_EQ(kMax
, set
.GetSize());
259 EXPECT_FALSE(set
.StartsWithUnknownVersion());
260 EXPECT_EQ(0, set
.begin()->version());
261 EXPECT_EQ(kMax
-1, static_cast<size_t>(set
.rbegin()->version()));
264 // Test that truncation happens as we reach the limit.
265 TEST_F(UnackedInvalidationSetTest
, Truncation
) {
266 size_t kMax
= UnackedInvalidationSet::kMaxBufferedInvalidations
;
268 for (size_t i
= 0; i
< kMax
+ 1; ++i
) {
269 Invalidation inv
= Invalidation::Init(kObjectId_
, i
, "payload");
270 unacked_invalidations_
.Add(inv
);
273 SingleObjectInvalidationSet set
= GetStoredInvalidations();
274 ASSERT_EQ(kMax
, set
.GetSize());
275 EXPECT_TRUE(set
.StartsWithUnknownVersion());
276 EXPECT_TRUE(set
.begin()->is_unknown_version());
277 EXPECT_EQ(kMax
, static_cast<size_t>(set
.rbegin()->version()));
280 // Test that we don't truncate while a handler is registered.
281 TEST_F(UnackedInvalidationSetTest
, RegistrationAndTruncation
) {
282 unacked_invalidations_
.SetHandlerIsRegistered();
284 size_t kMax
= UnackedInvalidationSet::kMaxBufferedInvalidations
;
286 for (size_t i
= 0; i
< kMax
+ 1; ++i
) {
287 Invalidation inv
= Invalidation::Init(kObjectId_
, i
, "payload");
288 unacked_invalidations_
.Add(inv
);
291 SingleObjectInvalidationSet set
= GetStoredInvalidations();
292 ASSERT_EQ(kMax
+1, set
.GetSize());
293 EXPECT_FALSE(set
.StartsWithUnknownVersion());
294 EXPECT_EQ(0, set
.begin()->version());
295 EXPECT_EQ(kMax
, static_cast<size_t>(set
.rbegin()->version()));
297 // Unregistering should re-enable truncation.
298 unacked_invalidations_
.SetHandlerIsUnregistered();
299 SingleObjectInvalidationSet set2
= GetStoredInvalidations();
300 ASSERT_EQ(kMax
, set2
.GetSize());
301 EXPECT_TRUE(set2
.StartsWithUnknownVersion());
302 EXPECT_TRUE(set2
.begin()->is_unknown_version());
303 EXPECT_EQ(kMax
, static_cast<size_t>(set2
.rbegin()->version()));
306 // Test acknowledgement.
307 TEST_F(UnackedInvalidationSetTest
, Acknowledge
) {
308 // inv2 is included in this test just to make sure invalidations that
309 // are supposed to be unaffected by this operation will be unaffected.
311 // We don't expect to be receiving acks or drops unless this flag is set.
312 // Not that it makes much of a difference in behavior.
313 unacked_invalidations_
.SetHandlerIsRegistered();
315 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
316 Invalidation inv2
= Invalidation::InitUnknownVersion(kObjectId_
);
317 AckHandle inv1_handle
= inv1
.ack_handle();
319 unacked_invalidations_
.Add(inv1
);
320 unacked_invalidations_
.Add(inv2
);
322 unacked_invalidations_
.Acknowledge(inv1_handle
);
324 SingleObjectInvalidationSet set
= GetStoredInvalidations();
325 EXPECT_EQ(1U, set
.GetSize());
326 EXPECT_TRUE(set
.StartsWithUnknownVersion());
330 TEST_F(UnackedInvalidationSetTest
, Drop
) {
331 // inv2 is included in this test just to make sure invalidations that
332 // are supposed to be unaffected by this operation will be unaffected.
334 // We don't expect to be receiving acks or drops unless this flag is set.
335 // Not that it makes much of a difference in behavior.
336 unacked_invalidations_
.SetHandlerIsRegistered();
338 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
339 Invalidation inv2
= Invalidation::Init(kObjectId_
, 15, "payload");
340 AckHandle inv1_handle
= inv1
.ack_handle();
342 unacked_invalidations_
.Add(inv1
);
343 unacked_invalidations_
.Add(inv2
);
345 unacked_invalidations_
.Drop(inv1_handle
);
347 SingleObjectInvalidationSet set
= GetStoredInvalidations();
348 ASSERT_EQ(2U, set
.GetSize());
349 EXPECT_TRUE(set
.StartsWithUnknownVersion());
350 EXPECT_EQ(15, set
.rbegin()->version());
353 class UnackedInvalidationSetSerializationTest
354 : public UnackedInvalidationSetTest
{
356 UnackedInvalidationSet
SerializeDeserialize() {
357 scoped_ptr
<base::DictionaryValue
> value
= unacked_invalidations_
.ToValue();
358 UnackedInvalidationSet
deserialized(kObjectId_
);
359 deserialized
.ResetFromValue(*value
.get());
364 TEST_F(UnackedInvalidationSetSerializationTest
, Empty
) {
365 UnackedInvalidationSet deserialized
= SerializeDeserialize();
366 EXPECT_THAT(unacked_invalidations_
, Eq(deserialized
));
369 TEST_F(UnackedInvalidationSetSerializationTest
, OneInvalidation
) {
370 Invalidation inv
= Invalidation::Init(kObjectId_
, 10, "payload");
371 unacked_invalidations_
.Add(inv
);
373 UnackedInvalidationSet deserialized
= SerializeDeserialize();
374 EXPECT_THAT(unacked_invalidations_
, Eq(deserialized
));
377 TEST_F(UnackedInvalidationSetSerializationTest
, WithUnknownVersion
) {
378 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
379 Invalidation inv2
= Invalidation::InitUnknownVersion(kObjectId_
);
380 Invalidation inv3
= Invalidation::InitUnknownVersion(kObjectId_
);
381 unacked_invalidations_
.Add(inv1
);
382 unacked_invalidations_
.Add(inv2
);
383 unacked_invalidations_
.Add(inv3
);
385 UnackedInvalidationSet deserialized
= SerializeDeserialize();
386 EXPECT_THAT(unacked_invalidations_
, Eq(deserialized
));
391 } // namespace syncer