- add sources.
[platform/framework/web/crosswalk.git] / src / sync / notifier / unacked_invalidation_set_unittest.cc
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.
4
5 #include "sync/notifier/unacked_invalidation_set.h"
6
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"
12
13 namespace syncer {
14
15 // Start with some helper functions and classes.
16
17 using ::testing::MakeMatcher;
18 using ::testing::MatchResultListener;
19 using ::testing::Matcher;
20 using ::testing::MatcherInterface;
21 using ::testing::PrintToString;
22
23 void PrintTo(
24     const UnackedInvalidationSet& invalidations, ::std::ostream* os);
25
26 void PrintTo(
27     const UnackedInvalidationsMap& map, ::std::ostream* os);
28
29 ::testing::Matcher<const UnackedInvalidationSet&> Eq(
30     const UnackedInvalidationSet& expected);
31
32 ::testing::Matcher<const UnackedInvalidationsMap&> Eq(
33     const UnackedInvalidationsMap& expected);
34
35 class UnackedInvalidationSetEqMatcher
36     : public testing::MatcherInterface<const UnackedInvalidationSet&> {
37  public:
38   explicit UnackedInvalidationSetEqMatcher(
39       const UnackedInvalidationSet& expected);
40
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;
46
47  private:
48   const UnackedInvalidationSet expected_;
49
50   DISALLOW_COPY_AND_ASSIGN(UnackedInvalidationSetEqMatcher);
51 };
52
53 UnackedInvalidationSetEqMatcher::UnackedInvalidationSetEqMatcher(
54     const UnackedInvalidationSet& expected)
55   : expected_(expected) {}
56
57 namespace {
58
59 struct InvalidationEq {
60   bool operator()(const syncer::Invalidation& a,
61                   const syncer::Invalidation& b) const {
62     return a.Equals(b);
63   }
64 };
65
66 }  // namespace
67
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
72   // instances.
73   //
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(),
80                     InvalidationEq());
81 }
82
83 void UnackedInvalidationSetEqMatcher::DescribeTo(::std::ostream* os) const {
84   *os << " is equal to " << PrintToString(expected_);
85 }
86
87 void UnackedInvalidationSetEqMatcher::DescribeNegationTo(
88     ::std::ostream* os) const {
89   *os << " isn't equal to " << PrintToString(expected_);
90 }
91
92 namespace {
93
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);
101   }
102   return object_id_invalidation_map;
103 }
104
105 class UnackedInvalidationsMapEqMatcher
106     : public testing::MatcherInterface<const UnackedInvalidationsMap&> {
107  public:
108   explicit UnackedInvalidationsMapEqMatcher(
109       const UnackedInvalidationsMap& expected);
110
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;
115
116  private:
117   const UnackedInvalidationsMap expected_;
118
119   DISALLOW_COPY_AND_ASSIGN(UnackedInvalidationsMapEqMatcher);
120 };
121
122 UnackedInvalidationsMapEqMatcher::UnackedInvalidationsMapEqMatcher(
123     const UnackedInvalidationsMap& expected)
124     : expected_(expected) {
125 }
126
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);
134
135   return expected_inv == actual_inv;
136 }
137
138 void UnackedInvalidationsMapEqMatcher::DescribeTo(
139     ::std::ostream* os) const {
140   *os << " is equal to " << PrintToString(expected_);
141 }
142
143 void UnackedInvalidationsMapEqMatcher::DescribeNegationTo(
144     ::std::ostream* os) const {
145   *os << " isn't equal to " << PrintToString(expected_);
146 }
147
148 }  // namespace
149
150 void PrintTo(const UnackedInvalidationSet& invalidations,
151              ::std::ostream* os) {
152   scoped_ptr<base::DictionaryValue> value = invalidations.ToValue();
153
154   std::string output;
155   JSONStringValueSerializer serializer(&output);
156   serializer.set_pretty_print(true);
157   serializer.Serialize(*value.get());
158
159   (*os) << output;
160 }
161
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());
167   }
168
169   std::string output;
170   JSONStringValueSerializer serializer(&output);
171   serializer.set_pretty_print(true);
172   serializer.Serialize(*list.get());
173
174   (*os) << output;
175 }
176
177 Matcher<const UnackedInvalidationSet&> Eq(
178     const UnackedInvalidationSet& expected) {
179   return MakeMatcher(new UnackedInvalidationSetEqMatcher(expected));
180 }
181
182 Matcher<const UnackedInvalidationsMap&> Eq(
183     const UnackedInvalidationsMap& expected) {
184   return MakeMatcher(new UnackedInvalidationsMapEqMatcher(expected));
185 }
186
187 class UnackedInvalidationSetTest : public testing::Test {
188  public:
189   UnackedInvalidationSetTest()
190       : kObjectId_(10, "ASDF"),
191         unacked_invalidations_(kObjectId_) {}
192
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_);
199     } else {
200       return SingleObjectInvalidationSet();
201     }
202   }
203
204   const invalidation::ObjectId kObjectId_;
205   UnackedInvalidationSet unacked_invalidations_;
206 };
207
208 namespace {
209
210 // Test storage and retrieval of zero invalidations.
211 TEST_F(UnackedInvalidationSetTest, Empty) {
212   EXPECT_EQ(0U, GetStoredInvalidations().GetSize());
213 }
214
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);
219
220   SingleObjectInvalidationSet set = GetStoredInvalidations();
221   ASSERT_EQ(1U, set.GetSize());
222   EXPECT_FALSE(set.StartsWithUnknownVersion());
223 }
224
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();
230
231   EXPECT_EQ(0U, GetStoredInvalidations().GetSize());
232 }
233
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);
242
243   SingleObjectInvalidationSet set = GetStoredInvalidations();
244   ASSERT_EQ(2U, set.GetSize());
245   EXPECT_TRUE(set.StartsWithUnknownVersion());
246 }
247
248 // Tests that no truncation occurs while we're under the limit.
249 TEST_F(UnackedInvalidationSetTest, NoTruncation) {
250   size_t kMax = UnackedInvalidationSet::kMaxBufferedInvalidations;
251
252   for (size_t i = 0; i < kMax; ++i) {
253     Invalidation inv = Invalidation::Init(kObjectId_, i, "payload");
254     unacked_invalidations_.Add(inv);
255   }
256
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()));
262 }
263
264 // Test that truncation happens as we reach the limit.
265 TEST_F(UnackedInvalidationSetTest, Truncation) {
266   size_t kMax = UnackedInvalidationSet::kMaxBufferedInvalidations;
267
268   for (size_t i = 0; i < kMax + 1; ++i) {
269     Invalidation inv = Invalidation::Init(kObjectId_, i, "payload");
270     unacked_invalidations_.Add(inv);
271   }
272
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()));
278 }
279
280 // Test that we don't truncate while a handler is registered.
281 TEST_F(UnackedInvalidationSetTest, RegistrationAndTruncation) {
282   unacked_invalidations_.SetHandlerIsRegistered();
283
284   size_t kMax = UnackedInvalidationSet::kMaxBufferedInvalidations;
285
286   for (size_t i = 0; i < kMax + 1; ++i) {
287     Invalidation inv = Invalidation::Init(kObjectId_, i, "payload");
288     unacked_invalidations_.Add(inv);
289   }
290
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()));
296
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()));
304 }
305
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.
310
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();
314
315   Invalidation inv1 = Invalidation::Init(kObjectId_, 10, "payload");
316   Invalidation inv2 = Invalidation::InitUnknownVersion(kObjectId_);
317   AckHandle inv1_handle = inv1.ack_handle();
318
319   unacked_invalidations_.Add(inv1);
320   unacked_invalidations_.Add(inv2);
321
322   unacked_invalidations_.Acknowledge(inv1_handle);
323
324   SingleObjectInvalidationSet set = GetStoredInvalidations();
325   EXPECT_EQ(1U, set.GetSize());
326   EXPECT_TRUE(set.StartsWithUnknownVersion());
327 }
328
329 // Test drops.
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.
333
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();
337
338   Invalidation inv1 = Invalidation::Init(kObjectId_, 10, "payload");
339   Invalidation inv2 = Invalidation::Init(kObjectId_, 15, "payload");
340   AckHandle inv1_handle = inv1.ack_handle();
341
342   unacked_invalidations_.Add(inv1);
343   unacked_invalidations_.Add(inv2);
344
345   unacked_invalidations_.Drop(inv1_handle);
346
347   SingleObjectInvalidationSet set = GetStoredInvalidations();
348   ASSERT_EQ(2U, set.GetSize());
349   EXPECT_TRUE(set.StartsWithUnknownVersion());
350   EXPECT_EQ(15, set.rbegin()->version());
351 }
352
353 class UnackedInvalidationSetSerializationTest
354     : public UnackedInvalidationSetTest {
355  public:
356   UnackedInvalidationSet SerializeDeserialize() {
357     scoped_ptr<base::DictionaryValue> value = unacked_invalidations_.ToValue();
358     UnackedInvalidationSet deserialized(kObjectId_);
359     deserialized.ResetFromValue(*value.get());
360     return deserialized;
361   }
362 };
363
364 TEST_F(UnackedInvalidationSetSerializationTest, Empty) {
365   UnackedInvalidationSet deserialized = SerializeDeserialize();
366   EXPECT_THAT(unacked_invalidations_, Eq(deserialized));
367 }
368
369 TEST_F(UnackedInvalidationSetSerializationTest, OneInvalidation) {
370   Invalidation inv = Invalidation::Init(kObjectId_, 10, "payload");
371   unacked_invalidations_.Add(inv);
372
373   UnackedInvalidationSet deserialized = SerializeDeserialize();
374   EXPECT_THAT(unacked_invalidations_, Eq(deserialized));
375 }
376
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);
384
385   UnackedInvalidationSet deserialized = SerializeDeserialize();
386   EXPECT_THAT(unacked_invalidations_, Eq(deserialized));
387 }
388
389 }  // namespace
390
391 }  // namespace syncer