OLD | NEW |
| (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 | |
OLD | NEW |