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 "sync/notifier/unacked_invalidation_set_test_util.h"
11 #include "testing/gtest/include/gtest/gtest.h"
15 class UnackedInvalidationSetTest
: public testing::Test
{
17 UnackedInvalidationSetTest()
18 : kObjectId_(10, "ASDF"),
19 unacked_invalidations_(kObjectId_
) {}
21 SingleObjectInvalidationSet
GetStoredInvalidations() {
22 ObjectIdInvalidationMap map
;
23 unacked_invalidations_
.ExportInvalidations(WeakHandle
<AckHandler
>(), &map
);
24 ObjectIdSet ids
= map
.GetObjectIds();
25 if (ids
.find(kObjectId_
) != ids
.end()) {
26 return map
.ForObject(kObjectId_
);
28 return SingleObjectInvalidationSet();
32 const invalidation::ObjectId kObjectId_
;
33 UnackedInvalidationSet unacked_invalidations_
;
38 // Test storage and retrieval of zero invalidations.
39 TEST_F(UnackedInvalidationSetTest
, Empty
) {
40 EXPECT_EQ(0U, GetStoredInvalidations().GetSize());
43 // Test storage and retrieval of a single invalidation.
44 TEST_F(UnackedInvalidationSetTest
, OneInvalidation
) {
45 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
46 unacked_invalidations_
.Add(inv1
);
48 SingleObjectInvalidationSet set
= GetStoredInvalidations();
49 ASSERT_EQ(1U, set
.GetSize());
50 EXPECT_FALSE(set
.StartsWithUnknownVersion());
53 // Test that calling Clear() returns us to the empty state.
54 TEST_F(UnackedInvalidationSetTest
, Clear
) {
55 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
56 unacked_invalidations_
.Add(inv1
);
57 unacked_invalidations_
.Clear();
59 EXPECT_EQ(0U, GetStoredInvalidations().GetSize());
62 // Test that repeated unknown version invalidations are squashed together.
63 TEST_F(UnackedInvalidationSetTest
, UnknownVersions
) {
64 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
65 Invalidation inv2
= Invalidation::InitUnknownVersion(kObjectId_
);
66 Invalidation inv3
= Invalidation::InitUnknownVersion(kObjectId_
);
67 unacked_invalidations_
.Add(inv1
);
68 unacked_invalidations_
.Add(inv2
);
69 unacked_invalidations_
.Add(inv3
);
71 SingleObjectInvalidationSet set
= GetStoredInvalidations();
72 ASSERT_EQ(2U, set
.GetSize());
73 EXPECT_TRUE(set
.StartsWithUnknownVersion());
76 // Tests that no truncation occurs while we're under the limit.
77 TEST_F(UnackedInvalidationSetTest
, NoTruncation
) {
78 size_t kMax
= UnackedInvalidationSet::kMaxBufferedInvalidations
;
80 for (size_t i
= 0; i
< kMax
; ++i
) {
81 Invalidation inv
= Invalidation::Init(kObjectId_
, i
, "payload");
82 unacked_invalidations_
.Add(inv
);
85 SingleObjectInvalidationSet set
= GetStoredInvalidations();
86 ASSERT_EQ(kMax
, set
.GetSize());
87 EXPECT_FALSE(set
.StartsWithUnknownVersion());
88 EXPECT_EQ(0, set
.begin()->version());
89 EXPECT_EQ(kMax
-1, static_cast<size_t>(set
.rbegin()->version()));
92 // Test that truncation happens as we reach the limit.
93 TEST_F(UnackedInvalidationSetTest
, Truncation
) {
94 size_t kMax
= UnackedInvalidationSet::kMaxBufferedInvalidations
;
96 for (size_t i
= 0; i
< kMax
+ 1; ++i
) {
97 Invalidation inv
= Invalidation::Init(kObjectId_
, i
, "payload");
98 unacked_invalidations_
.Add(inv
);
101 SingleObjectInvalidationSet set
= GetStoredInvalidations();
102 ASSERT_EQ(kMax
, set
.GetSize());
103 EXPECT_TRUE(set
.StartsWithUnknownVersion());
104 EXPECT_TRUE(set
.begin()->is_unknown_version());
105 EXPECT_EQ(kMax
, static_cast<size_t>(set
.rbegin()->version()));
108 // Test that we don't truncate while a handler is registered.
109 TEST_F(UnackedInvalidationSetTest
, RegistrationAndTruncation
) {
110 unacked_invalidations_
.SetHandlerIsRegistered();
112 size_t kMax
= UnackedInvalidationSet::kMaxBufferedInvalidations
;
114 for (size_t i
= 0; i
< kMax
+ 1; ++i
) {
115 Invalidation inv
= Invalidation::Init(kObjectId_
, i
, "payload");
116 unacked_invalidations_
.Add(inv
);
119 SingleObjectInvalidationSet set
= GetStoredInvalidations();
120 ASSERT_EQ(kMax
+1, set
.GetSize());
121 EXPECT_FALSE(set
.StartsWithUnknownVersion());
122 EXPECT_EQ(0, set
.begin()->version());
123 EXPECT_EQ(kMax
, static_cast<size_t>(set
.rbegin()->version()));
125 // Unregistering should re-enable truncation.
126 unacked_invalidations_
.SetHandlerIsUnregistered();
127 SingleObjectInvalidationSet set2
= GetStoredInvalidations();
128 ASSERT_EQ(kMax
, set2
.GetSize());
129 EXPECT_TRUE(set2
.StartsWithUnknownVersion());
130 EXPECT_TRUE(set2
.begin()->is_unknown_version());
131 EXPECT_EQ(kMax
, static_cast<size_t>(set2
.rbegin()->version()));
134 // Test acknowledgement.
135 TEST_F(UnackedInvalidationSetTest
, Acknowledge
) {
136 // inv2 is included in this test just to make sure invalidations that
137 // are supposed to be unaffected by this operation will be unaffected.
139 // We don't expect to be receiving acks or drops unless this flag is set.
140 // Not that it makes much of a difference in behavior.
141 unacked_invalidations_
.SetHandlerIsRegistered();
143 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
144 Invalidation inv2
= Invalidation::InitUnknownVersion(kObjectId_
);
145 AckHandle inv1_handle
= inv1
.ack_handle();
147 unacked_invalidations_
.Add(inv1
);
148 unacked_invalidations_
.Add(inv2
);
150 unacked_invalidations_
.Acknowledge(inv1_handle
);
152 SingleObjectInvalidationSet set
= GetStoredInvalidations();
153 EXPECT_EQ(1U, set
.GetSize());
154 EXPECT_TRUE(set
.StartsWithUnknownVersion());
158 TEST_F(UnackedInvalidationSetTest
, Drop
) {
159 // inv2 is included in this test just to make sure invalidations that
160 // are supposed to be unaffected by this operation will be unaffected.
162 // We don't expect to be receiving acks or drops unless this flag is set.
163 // Not that it makes much of a difference in behavior.
164 unacked_invalidations_
.SetHandlerIsRegistered();
166 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
167 Invalidation inv2
= Invalidation::Init(kObjectId_
, 15, "payload");
168 AckHandle inv1_handle
= inv1
.ack_handle();
170 unacked_invalidations_
.Add(inv1
);
171 unacked_invalidations_
.Add(inv2
);
173 unacked_invalidations_
.Drop(inv1_handle
);
175 SingleObjectInvalidationSet set
= GetStoredInvalidations();
176 ASSERT_EQ(2U, set
.GetSize());
177 EXPECT_TRUE(set
.StartsWithUnknownVersion());
178 EXPECT_EQ(15, set
.rbegin()->version());
181 class UnackedInvalidationSetSerializationTest
182 : public UnackedInvalidationSetTest
{
184 UnackedInvalidationSet
SerializeDeserialize() {
185 scoped_ptr
<base::DictionaryValue
> value
= unacked_invalidations_
.ToValue();
186 UnackedInvalidationSet
deserialized(kObjectId_
);
187 deserialized
.ResetFromValue(*value
.get());
192 TEST_F(UnackedInvalidationSetSerializationTest
, Empty
) {
193 UnackedInvalidationSet deserialized
= SerializeDeserialize();
194 EXPECT_THAT(unacked_invalidations_
, test_util::Eq(deserialized
));
197 TEST_F(UnackedInvalidationSetSerializationTest
, OneInvalidation
) {
198 Invalidation inv
= Invalidation::Init(kObjectId_
, 10, "payload");
199 unacked_invalidations_
.Add(inv
);
201 UnackedInvalidationSet deserialized
= SerializeDeserialize();
202 EXPECT_THAT(unacked_invalidations_
, test_util::Eq(deserialized
));
205 TEST_F(UnackedInvalidationSetSerializationTest
, WithUnknownVersion
) {
206 Invalidation inv1
= Invalidation::Init(kObjectId_
, 10, "payload");
207 Invalidation inv2
= Invalidation::InitUnknownVersion(kObjectId_
);
208 Invalidation inv3
= Invalidation::InitUnknownVersion(kObjectId_
);
209 unacked_invalidations_
.Add(inv1
);
210 unacked_invalidations_
.Add(inv2
);
211 unacked_invalidations_
.Add(inv3
);
213 UnackedInvalidationSet deserialized
= SerializeDeserialize();
214 EXPECT_THAT(unacked_invalidations_
, test_util::Eq(deserialized
));
219 } // namespace syncer