Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: chrome/browser/sync/invalidations/invalidator_storage_unittest.cc

Issue 13991017: Commit InvalidationService implementations (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Another attempt to fix Android Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
6 #include "chrome/browser/sync/invalidations/invalidator_storage.h"
7
8 #include "base/bind.h"
9 #include "base/message_loop.h"
10 #include "base/message_loop_proxy.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/string_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/test/base/testing_pref_service_syncable.h"
16 #include "sync/internal_api/public/base/invalidation_test_util.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 using syncer::InvalidationStateMap;
21
22 namespace browser_sync {
23
24 namespace {
25
26 const char kSourceKey[] = "source";
27 const char kNameKey[] = "name";
28 const char kMaxVersionKey[] = "max-version";
29 const char kPayloadKey[] = "payload";
30 const char kCurrentAckHandleKey[] = "current-ack";
31 const char kExpectedAckHandleKey[] = "expected-ack";
32
33 const int kChromeSyncSourceId = 1004;
34
35 void GenerateAckHandlesTestHelper(syncer::AckHandleMap* output,
36 const syncer::AckHandleMap& input) {
37 *output = input;
38 }
39
40 } // namespace
41
42 class InvalidatorStorageTest : public testing::Test {
43 public:
44 InvalidatorStorageTest()
45 : kBookmarksId_(kChromeSyncSourceId, "BOOKMARK"),
46 kPreferencesId_(kChromeSyncSourceId, "PREFERENCE"),
47 kAppNotificationsId_(kChromeSyncSourceId, "APP_NOTIFICATION"),
48 kAutofillId_(kChromeSyncSourceId, "AUTOFILL") {}
49
50 virtual void SetUp() {
51 InvalidatorStorage::RegisterUserPrefs(pref_service_.registry());
52 }
53
54 protected:
55 TestingPrefServiceSyncable pref_service_;
56
57 const invalidation::ObjectId kBookmarksId_;
58 const invalidation::ObjectId kPreferencesId_;
59 const invalidation::ObjectId kAppNotificationsId_;
60 const invalidation::ObjectId kAutofillId_;
61
62 MessageLoop loop_;
63 };
64
65 // Set invalidation states for various keys and verify that they are written and
66 // read back correctly.
67 TEST_F(InvalidatorStorageTest, SetMaxVersionAndPayload) {
68 InvalidatorStorage storage(&pref_service_);
69
70 InvalidationStateMap expected_states;
71 EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
72
73 expected_states[kBookmarksId_].version = 2;
74 expected_states[kBookmarksId_].payload = "hello";
75 storage.SetMaxVersionAndPayload(kBookmarksId_, 2, "hello");
76 EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
77
78 expected_states[kPreferencesId_].version = 5;
79 storage.SetMaxVersionAndPayload(kPreferencesId_, 5, std::string());
80 EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
81
82 expected_states[kAppNotificationsId_].version = 3;
83 expected_states[kAppNotificationsId_].payload = "world";
84 storage.SetMaxVersionAndPayload(kAppNotificationsId_, 3, "world");
85 EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
86
87 expected_states[kAppNotificationsId_].version = 4;
88 expected_states[kAppNotificationsId_].payload = "again";
89 storage.SetMaxVersionAndPayload(kAppNotificationsId_, 4, "again");
90 EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
91 }
92
93 // Forgetting an entry should cause that entry to be deleted.
94 TEST_F(InvalidatorStorageTest, Forget) {
95 InvalidatorStorage storage(&pref_service_);
96 EXPECT_TRUE(storage.GetAllInvalidationStates().empty());
97
98 InvalidationStateMap expected_states;
99 expected_states[kBookmarksId_].version = 2;
100 expected_states[kBookmarksId_].payload = "a";
101 expected_states[kPreferencesId_].version = 5;
102 expected_states[kPreferencesId_].payload = "b";
103 storage.SetMaxVersionAndPayload(kBookmarksId_, 2, "a");
104 storage.SetMaxVersionAndPayload(kPreferencesId_, 5, "b");
105 EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
106
107 expected_states.erase(kPreferencesId_);
108 syncer::ObjectIdSet to_forget;
109 to_forget.insert(kPreferencesId_);
110 storage.Forget(to_forget);
111 EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
112 }
113
114 // Clearing the storage should erase all version map entries, bootstrap data,
115 // and the client ID.
116 TEST_F(InvalidatorStorageTest, Clear) {
117 InvalidatorStorage storage(&pref_service_);
118 EXPECT_TRUE(storage.GetAllInvalidationStates().empty());
119 EXPECT_TRUE(storage.GetBootstrapData().empty());
120 EXPECT_TRUE(storage.GetInvalidatorClientId().empty());
121
122 storage.SetInvalidatorClientId("fake_id");
123 EXPECT_EQ("fake_id", storage.GetInvalidatorClientId());
124
125 storage.SetBootstrapData("test");
126 EXPECT_EQ("test", storage.GetBootstrapData());
127
128 {
129 InvalidationStateMap expected_states;
130 expected_states[kAppNotificationsId_].version = 3;
131 storage.SetMaxVersionAndPayload(kAppNotificationsId_, 3, std::string());
132 EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
133 }
134
135 storage.Clear();
136
137 EXPECT_TRUE(storage.GetAllInvalidationStates().empty());
138 EXPECT_TRUE(storage.GetBootstrapData().empty());
139 EXPECT_TRUE(storage.GetInvalidatorClientId().empty());
140 }
141
142 TEST_F(InvalidatorStorageTest, SerializeEmptyMap) {
143 InvalidationStateMap empty_map;
144 base::ListValue list;
145 InvalidatorStorage::SerializeToList(empty_map, &list);
146 EXPECT_TRUE(list.empty());
147 }
148
149 // Make sure we don't choke on a variety of malformed input.
150 TEST_F(InvalidatorStorageTest, DeserializeFromListInvalidFormat) {
151 InvalidationStateMap map;
152 base::ListValue list_with_invalid_format;
153 DictionaryValue* value;
154
155 // The various cases below use distinct values to make it easier to track down
156 // failures.
157 value = new DictionaryValue();
158 list_with_invalid_format.Append(value);
159
160 value = new DictionaryValue();
161 value->SetString("completely", "invalid");
162 list_with_invalid_format.Append(value);
163
164 // Missing two required fields
165 value = new DictionaryValue();
166 value->SetString(kSourceKey, "10");
167 list_with_invalid_format.Append(value);
168
169 value = new DictionaryValue();
170 value->SetString(kNameKey, "missing source and version");
171 list_with_invalid_format.Append(value);
172
173 value = new DictionaryValue();
174 value->SetString(kMaxVersionKey, "3");
175 list_with_invalid_format.Append(value);
176
177 // Missing one required field
178 value = new DictionaryValue();
179 value->SetString(kSourceKey, "14");
180 value->SetString(kNameKey, "missing version");
181 list_with_invalid_format.Append(value);
182
183 value = new DictionaryValue();
184 value->SetString(kSourceKey, "233");
185 value->SetString(kMaxVersionKey, "5");
186 list_with_invalid_format.Append(value);
187
188 value = new DictionaryValue();
189 value->SetString(kNameKey, "missing source");
190 value->SetString(kMaxVersionKey, "25");
191 list_with_invalid_format.Append(value);
192
193 // Invalid values in fields
194 value = new DictionaryValue();
195 value->SetString(kSourceKey, "a");
196 value->SetString(kNameKey, "bad source");
197 value->SetString(kMaxVersionKey, "12");
198 list_with_invalid_format.Append(value);
199
200 value = new DictionaryValue();
201 value->SetString(kSourceKey, "1");
202 value->SetString(kNameKey, "bad max version");
203 value->SetString(kMaxVersionKey, "a");
204 list_with_invalid_format.Append(value);
205
206 // And finally something that should work.
207 invalidation::ObjectId valid_id(42, "this should work");
208 value = new DictionaryValue();
209 value->SetString(kSourceKey, "42");
210 value->SetString(kNameKey, valid_id.name());
211 value->SetString(kMaxVersionKey, "20");
212 list_with_invalid_format.Append(value);
213
214 InvalidatorStorage::DeserializeFromList(list_with_invalid_format, &map);
215
216 EXPECT_EQ(1U, map.size());
217 EXPECT_EQ(20, map[valid_id].version);
218 }
219
220 // Tests behavior when there are duplicate entries for a single key. The value
221 // of the last entry with that key should be used in the version map.
222 TEST_F(InvalidatorStorageTest, DeserializeFromListWithDuplicates) {
223 InvalidationStateMap map;
224 base::ListValue list;
225 DictionaryValue* value;
226
227 value = new DictionaryValue();
228 value->SetString(kSourceKey, base::IntToString(kBookmarksId_.source()));
229 value->SetString(kNameKey, kBookmarksId_.name());
230 value->SetString(kMaxVersionKey, "20");
231 list.Append(value);
232 value = new DictionaryValue();
233 value->SetString(kSourceKey, base::IntToString(kAutofillId_.source()));
234 value->SetString(kNameKey, kAutofillId_.name());
235 value->SetString(kMaxVersionKey, "10");
236 list.Append(value);
237 value = new DictionaryValue();
238 value->SetString(kSourceKey, base::IntToString(kBookmarksId_.source()));
239 value->SetString(kNameKey, kBookmarksId_.name());
240 value->SetString(kMaxVersionKey, "15");
241 list.Append(value);
242
243 InvalidatorStorage::DeserializeFromList(list, &map);
244 EXPECT_EQ(2U, map.size());
245 EXPECT_EQ(10, map[kAutofillId_].version);
246 EXPECT_EQ(15, map[kBookmarksId_].version);
247 }
248
249 TEST_F(InvalidatorStorageTest, DeserializeFromEmptyList) {
250 InvalidationStateMap map;
251 base::ListValue list;
252 InvalidatorStorage::DeserializeFromList(list, &map);
253 EXPECT_TRUE(map.empty());
254 }
255
256 // Tests that deserializing a well-formed value results in the expected state
257 // map.
258 TEST_F(InvalidatorStorageTest, DeserializeFromListBasic) {
259 InvalidationStateMap map;
260 base::ListValue list;
261 DictionaryValue* value;
262 syncer::AckHandle ack_handle_1 = syncer::AckHandle::CreateUnique();
263 syncer::AckHandle ack_handle_2 = syncer::AckHandle::CreateUnique();
264
265 value = new DictionaryValue();
266 value->SetString(kSourceKey,
267 base::IntToString(kAppNotificationsId_.source()));
268 value->SetString(kNameKey, kAppNotificationsId_.name());
269 value->SetString(kMaxVersionKey, "20");
270 value->SetString(kPayloadKey, "testing");
271 value->Set(kCurrentAckHandleKey, ack_handle_1.ToValue().release());
272 value->Set(kExpectedAckHandleKey, ack_handle_2.ToValue().release());
273 list.Append(value);
274
275 InvalidatorStorage::DeserializeFromList(list, &map);
276 EXPECT_EQ(1U, map.size());
277 EXPECT_EQ(20, map[kAppNotificationsId_].version);
278 EXPECT_EQ("testing", map[kAppNotificationsId_].payload);
279 EXPECT_THAT(map[kAppNotificationsId_].current, Eq(ack_handle_1));
280 EXPECT_THAT(map[kAppNotificationsId_].expected, Eq(ack_handle_2));
281 }
282
283 // Tests that deserializing well-formed values when optional parameters are
284 // omitted works.
285 TEST_F(InvalidatorStorageTest, DeserializeFromListMissingOptionalValues) {
286 InvalidationStateMap map;
287 base::ListValue list;
288 DictionaryValue* value;
289 syncer::AckHandle ack_handle = syncer::AckHandle::CreateUnique();
290
291 // Payload missing because of an upgrade from a previous browser version that
292 // didn't set the field.
293 value = new DictionaryValue();
294 value->SetString(kSourceKey, base::IntToString(kAutofillId_.source()));
295 value->SetString(kNameKey, kAutofillId_.name());
296 value->SetString(kMaxVersionKey, "10");
297 list.Append(value);
298 // A crash between SetMaxVersion() and a callback from GenerateAckHandles()
299 // could result in this state.
300 value = new DictionaryValue();
301 value->SetString(kSourceKey, base::IntToString(kBookmarksId_.source()));
302 value->SetString(kNameKey, kBookmarksId_.name());
303 value->SetString(kMaxVersionKey, "15");
304 value->SetString(kPayloadKey, "hello");
305 list.Append(value);
306 // Never acknowledged, so current ack handle is unset.
307 value = new DictionaryValue();
308 value->SetString(kSourceKey, base::IntToString(kPreferencesId_.source()));
309 value->SetString(kNameKey, kPreferencesId_.name());
310 value->SetString(kMaxVersionKey, "20");
311 value->SetString(kPayloadKey, "world");
312 value->Set(kExpectedAckHandleKey, ack_handle.ToValue().release());
313 list.Append(value);
314
315 InvalidatorStorage::DeserializeFromList(list, &map);
316 EXPECT_EQ(3U, map.size());
317
318 EXPECT_EQ(10, map[kAutofillId_].version);
319 EXPECT_EQ("", map[kAutofillId_].payload);
320 EXPECT_FALSE(map[kAutofillId_].current.IsValid());
321 EXPECT_FALSE(map[kAutofillId_].expected.IsValid());
322
323 EXPECT_EQ(15, map[kBookmarksId_].version);
324 EXPECT_EQ("hello", map[kBookmarksId_].payload);
325 EXPECT_FALSE(map[kBookmarksId_].current.IsValid());
326 EXPECT_FALSE(map[kBookmarksId_].expected.IsValid());
327
328 EXPECT_EQ(20, map[kPreferencesId_].version);
329 EXPECT_EQ("world", map[kPreferencesId_].payload);
330 EXPECT_FALSE(map[kPreferencesId_].current.IsValid());
331 EXPECT_THAT(map[kPreferencesId_].expected, Eq(ack_handle));
332 }
333
334 // Tests for legacy deserialization code.
335 TEST_F(InvalidatorStorageTest, DeserializeMapOutOfRange) {
336 InvalidationStateMap map;
337 base::DictionaryValue dict_with_out_of_range_type;
338
339 dict_with_out_of_range_type.SetString(
340 base::IntToString(syncer::TOP_LEVEL_FOLDER), "100");
341 dict_with_out_of_range_type.SetString(
342 base::IntToString(syncer::BOOKMARKS), "5");
343
344 InvalidatorStorage::DeserializeMap(&dict_with_out_of_range_type, &map);
345
346 EXPECT_EQ(1U, map.size());
347 EXPECT_EQ(5, map[kBookmarksId_].version);
348 }
349
350 TEST_F(InvalidatorStorageTest, DeserializeMapInvalidFormat) {
351 InvalidationStateMap map;
352 base::DictionaryValue dict_with_invalid_format;
353
354 dict_with_invalid_format.SetString("whoops", "5");
355 dict_with_invalid_format.SetString("ohnoes", "whoops");
356 dict_with_invalid_format.SetString(
357 base::IntToString(syncer::BOOKMARKS), "ohnoes");
358 dict_with_invalid_format.SetString(
359 base::IntToString(syncer::AUTOFILL), "10");
360
361 InvalidatorStorage::DeserializeMap(&dict_with_invalid_format, &map);
362
363 EXPECT_EQ(1U, map.size());
364 EXPECT_EQ(10, map[kAutofillId_].version);
365 }
366
367 TEST_F(InvalidatorStorageTest, DeserializeMapEmptyDictionary) {
368 InvalidationStateMap map;
369 base::DictionaryValue dict;
370 InvalidatorStorage::DeserializeMap(&dict, &map);
371 EXPECT_TRUE(map.empty());
372 }
373
374 TEST_F(InvalidatorStorageTest, DeserializeMapBasic) {
375 InvalidationStateMap map;
376 base::DictionaryValue dict;
377
378 dict.SetString(base::IntToString(syncer::AUTOFILL), "10");
379 dict.SetString(base::IntToString(syncer::BOOKMARKS), "15");
380
381 InvalidatorStorage::DeserializeMap(&dict, &map);
382 EXPECT_EQ(2U, map.size());
383 EXPECT_EQ(10, map[kAutofillId_].version);
384 EXPECT_EQ(15, map[kBookmarksId_].version);
385 }
386
387 // Test that the migration code for the legacy preference works as expected.
388 // Migration should happen on construction of InvalidatorStorage.
389 TEST_F(InvalidatorStorageTest, MigrateLegacyPreferences) {
390 base::DictionaryValue* legacy_dict = new DictionaryValue;
391 legacy_dict->SetString(base::IntToString(syncer::AUTOFILL), "10");
392 legacy_dict->SetString(base::IntToString(syncer::BOOKMARKS), "32");
393 legacy_dict->SetString(base::IntToString(syncer::PREFERENCES), "54");
394 pref_service_.SetUserPref(prefs::kSyncMaxInvalidationVersions, legacy_dict);
395 InvalidatorStorage storage(&pref_service_);
396
397 // Legacy pref should be cleared.
398 const base::DictionaryValue* dict =
399 pref_service_.GetDictionary(prefs::kSyncMaxInvalidationVersions);
400 EXPECT_TRUE(dict->empty());
401
402 // Validate the new pref is set correctly.
403 InvalidationStateMap map;
404 const base::ListValue* list =
405 pref_service_.GetList(prefs::kInvalidatorMaxInvalidationVersions);
406 InvalidatorStorage::DeserializeFromList(*list, &map);
407
408 EXPECT_EQ(3U, map.size());
409 EXPECT_EQ(10, map[kAutofillId_].version);
410 EXPECT_EQ(32, map[kBookmarksId_].version);
411 EXPECT_EQ(54, map[kPreferencesId_].version);
412 }
413
414 TEST_F(InvalidatorStorageTest, SetGetNotifierClientId) {
415 InvalidatorStorage storage(&pref_service_);
416 const std::string client_id("fK6eDzAIuKqx9A4+93bljg==");
417
418 storage.SetInvalidatorClientId(client_id);
419 EXPECT_EQ(client_id, storage.GetInvalidatorClientId());
420 }
421
422 TEST_F(InvalidatorStorageTest, SetGetBootstrapData) {
423 InvalidatorStorage storage(&pref_service_);
424 const std::string mess("n\0tK\0\0l\344", 8);
425 ASSERT_FALSE(IsStringUTF8(mess));
426
427 storage.SetBootstrapData(mess);
428 EXPECT_EQ(mess, storage.GetBootstrapData());
429 }
430
431 // Test that we correctly generate ack handles, acknowledge them, and persist
432 // them.
433 TEST_F(InvalidatorStorageTest, GenerateAckHandlesAndAcknowledge) {
434 InvalidatorStorage storage(&pref_service_);
435 syncer::ObjectIdSet ids;
436 InvalidationStateMap state_map;
437 syncer::AckHandleMap ack_handle_map;
438 syncer::AckHandleMap::const_iterator it;
439
440 // Test that it works as expected if the key doesn't already exist in the map,
441 // e.g. the first invalidation received for the object ID was not for a
442 // specific version.
443 ids.insert(kAutofillId_);
444 storage.GenerateAckHandles(
445 ids, base::MessageLoopProxy::current(),
446 base::Bind(&GenerateAckHandlesTestHelper, &ack_handle_map));
447 loop_.RunUntilIdle();
448 EXPECT_EQ(1U, ack_handle_map.size());
449 it = ack_handle_map.find(kAutofillId_);
450 // Android STL appears to be buggy and causes gtest's IsContainerTest<> to
451 // treat an iterator as a STL container so we use != instead of ASSERT_NE.
452 ASSERT_TRUE(ack_handle_map.end() != it);
453 EXPECT_TRUE(it->second.IsValid());
454 state_map[kAutofillId_].expected = it->second;
455 EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
456
457 storage.Acknowledge(kAutofillId_, it->second);
458 state_map[kAutofillId_].current = it->second;
459 EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
460
461 ids.clear();
462
463 // Test that it works as expected if the key already exists.
464 state_map[kBookmarksId_].version = 11;
465 state_map[kBookmarksId_].payload = "hello";
466 storage.SetMaxVersionAndPayload(kBookmarksId_, 11, "hello");
467 EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
468 ids.insert(kBookmarksId_);
469 storage.GenerateAckHandles(
470 ids, base::MessageLoopProxy::current(),
471 base::Bind(&GenerateAckHandlesTestHelper, &ack_handle_map));
472 loop_.RunUntilIdle();
473 EXPECT_EQ(1U, ack_handle_map.size());
474 it = ack_handle_map.find(kBookmarksId_);
475 ASSERT_TRUE(ack_handle_map.end() != it);
476 EXPECT_TRUE(it->second.IsValid());
477 state_map[kBookmarksId_].expected = it->second;
478 EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
479
480 storage.Acknowledge(kBookmarksId_, it->second);
481 state_map[kBookmarksId_].current = it->second;
482 EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
483
484 // Finally, test that the ack handles are updated if we're asked to generate
485 // another ack handle for the same object ID.
486 state_map[kBookmarksId_].version = 12;
487 state_map[kBookmarksId_].payload = "world";
488 storage.SetMaxVersionAndPayload(kBookmarksId_, 12, "world");
489 EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
490 ids.insert(kBookmarksId_);
491 storage.GenerateAckHandles(
492 ids, base::MessageLoopProxy::current(),
493 base::Bind(&GenerateAckHandlesTestHelper, &ack_handle_map));
494 loop_.RunUntilIdle();
495 EXPECT_EQ(1U, ack_handle_map.size());
496 it = ack_handle_map.find(kBookmarksId_);
497 ASSERT_TRUE(ack_handle_map.end() != it);
498 EXPECT_TRUE(it->second.IsValid());
499 state_map[kBookmarksId_].expected = it->second;
500 EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
501
502 storage.Acknowledge(kBookmarksId_, it->second);
503 state_map[kBookmarksId_].current = it->second;
504 EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
505 }
506
507 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698