Chromium Code Reviews| Index: chrome/browser/sync/invalidations/invalidator_storage_unittest.cc |
| diff --git a/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc b/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc |
| index 850c574052c31f500237126e1024977f67722f11..a11d2072c3e815dbcfda6cdbee5c5ef6ab0badec 100644 |
| --- a/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc |
| +++ b/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc |
| @@ -5,11 +5,14 @@ |
| #include "chrome/browser/sync/invalidations/invalidator_storage.h" |
| +#include "base/bind.h" |
| #include "base/message_loop.h" |
| +#include "base/message_loop_proxy.h" |
| #include "base/string_number_conversions.h" |
| #include "base/string_util.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/testing_pref_service.h" |
| +#include "sync/internal_api/public/base/invalidation_test_util.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| @@ -22,9 +25,17 @@ namespace { |
| const char kSourceKey[] = "source"; |
| const char kNameKey[] = "name"; |
| const char kMaxVersionKey[] = "max-version"; |
| +const char kPayloadKey[] = "payload"; |
| +const char kCurrentAckHandleKey[] = "current-ack"; |
| +const char kExpectedAckHandleKey[] = "expected-ack"; |
| const int kChromeSyncSourceId = 1004; |
| +void GenerateAckHandlesTestHelper(syncer::AckHandleMap* output, |
| + const syncer::AckHandleMap& input) { |
| + *output = input; |
| +} |
| + |
| } // namespace |
| class InvalidatorStorageTest : public testing::Test { |
| @@ -43,7 +54,6 @@ class InvalidatorStorageTest : public testing::Test { |
| const invalidation::ObjectId kAppNotificationsId_; |
| const invalidation::ObjectId kAutofillId_; |
| - private: |
| MessageLoop loop_; |
| }; |
| @@ -56,19 +66,22 @@ TEST_F(InvalidatorStorageTest, MaxInvalidationVersions) { |
| EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates()); |
| expected_max_versions[kBookmarksId_].version = 2; |
| - storage.SetMaxVersion(kBookmarksId_, 2); |
| + expected_max_versions[kBookmarksId_].payload = "hello"; |
| + storage.SetMaxVersionAndPayload(kBookmarksId_, 2, "hello"); |
| EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates()); |
| expected_max_versions[kPreferencesId_].version = 5; |
| - storage.SetMaxVersion(kPreferencesId_, 5); |
| + storage.SetMaxVersionAndPayload(kPreferencesId_, 5, std::string()); |
| EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates()); |
| expected_max_versions[kAppNotificationsId_].version = 3; |
| - storage.SetMaxVersion(kAppNotificationsId_, 3); |
| + expected_max_versions[kAppNotificationsId_].payload = "world"; |
| + storage.SetMaxVersionAndPayload(kAppNotificationsId_, 3, "world"); |
| EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates()); |
| expected_max_versions[kAppNotificationsId_].version = 4; |
| - storage.SetMaxVersion(kAppNotificationsId_, 4); |
| + expected_max_versions[kAppNotificationsId_].payload = "again"; |
| + storage.SetMaxVersionAndPayload(kAppNotificationsId_, 4, "again"); |
| EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates()); |
| } |
| @@ -79,9 +92,11 @@ TEST_F(InvalidatorStorageTest, Forget) { |
| InvalidationStateMap expected_max_versions; |
|
akalin
2012/11/28 00:11:42
names
dcheng
2012/11/30 01:42:54
Done.
|
| expected_max_versions[kBookmarksId_].version = 2; |
| + expected_max_versions[kBookmarksId_].payload = "a"; |
| expected_max_versions[kPreferencesId_].version = 5; |
| - storage.SetMaxVersion(kBookmarksId_, 2); |
| - storage.SetMaxVersion(kPreferencesId_, 5); |
| + expected_max_versions[kPreferencesId_].payload = "b"; |
| + storage.SetMaxVersionAndPayload(kBookmarksId_, 2, "a"); |
| + storage.SetMaxVersionAndPayload(kPreferencesId_, 5, "b"); |
| EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates()); |
| expected_max_versions.erase(kPreferencesId_); |
| @@ -103,7 +118,7 @@ TEST_F(InvalidatorStorageTest, Clear) { |
| { |
| InvalidationStateMap expected_max_versions; |
| expected_max_versions[kAppNotificationsId_].version = 3; |
| - storage.SetMaxVersion(kAppNotificationsId_, 3); |
| + storage.SetMaxVersionAndPayload(kAppNotificationsId_, 3, std::string()); |
| EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates()); |
| } |
| @@ -150,11 +165,6 @@ TEST_F(InvalidatorStorageTest, DeserializeFromListInvalidFormat) { |
| // Missing one required field |
| value = new DictionaryValue(); |
| - value->SetString(kSourceKey, "14"); |
| - value->SetString(kNameKey, "missing version"); |
| - list_with_invalid_format.Append(value); |
| - |
| - value = new DictionaryValue(); |
| value->SetString(kSourceKey, "233"); |
| value->SetString(kMaxVersionKey, "5"); |
| list_with_invalid_format.Append(value); |
| @@ -234,21 +244,62 @@ TEST_F(InvalidatorStorageTest, DeserializeFromListBasic) { |
| base::ListValue list; |
| DictionaryValue* value; |
| + // Payload missing because of an upgrade from a previous browser version that |
| + // didn't set the field. |
| value = new DictionaryValue(); |
| value->SetString(kSourceKey, base::IntToString(kAutofillId_.source())); |
| value->SetString(kNameKey, kAutofillId_.name()); |
| value->SetString(kMaxVersionKey, "10"); |
| list.Append(value); |
| + // A crash between SetMaxVersion() and a callback from GenerateAckHandles() |
| + // could result in this state. |
| value = new DictionaryValue(); |
| value->SetString(kSourceKey, base::IntToString(kBookmarksId_.source())); |
| value->SetString(kNameKey, kBookmarksId_.name()); |
| value->SetString(kMaxVersionKey, "15"); |
| + value->SetString(kPayloadKey, "hello"); |
| + list.Append(value); |
| + syncer::AckHandle ack_handle_1 = syncer::AckHandle::CreateUnique(); |
| + syncer::AckHandle ack_handle_2 = syncer::AckHandle::CreateUnique(); |
| + syncer::AckHandle ack_handle_3 = syncer::AckHandle::CreateUnique(); |
| + syncer::AckHandle ack_handle_4 = syncer::AckHandle::CreateUnique(); |
| + // We've never received an invalidation for a specific version, so no max |
| + // version or payload information. |
| + value = new DictionaryValue(); |
| + value->SetString(kSourceKey, base::IntToString(kPreferencesId_.source())); |
| + value->SetString(kNameKey, kPreferencesId_.name()); |
| + value->Set(kCurrentAckHandleKey, ack_handle_1.ToValue().release()); |
| + value->Set(kExpectedAckHandleKey, ack_handle_2.ToValue().release()); |
| + list.Append(value); |
| + // All fields set. |
| + value = new DictionaryValue(); |
| + value->SetString(kSourceKey, |
| + base::IntToString(kAppNotificationsId_.source())); |
| + value->SetString(kNameKey, kAppNotificationsId_.name()); |
| + value->SetString(kMaxVersionKey, "20"); |
| + value->SetString(kPayloadKey, "world"); |
| + value->Set(kCurrentAckHandleKey, ack_handle_3.ToValue().release()); |
| + value->Set(kExpectedAckHandleKey, ack_handle_4.ToValue().release()); |
| list.Append(value); |
| InvalidatorStorage::DeserializeFromList(list, &map); |
| - EXPECT_EQ(2U, map.size()); |
| + EXPECT_EQ(4U, map.size()); |
| EXPECT_EQ(10, map[kAutofillId_].version); |
| + EXPECT_EQ(std::string(), map[kAutofillId_].payload); |
| + EXPECT_FALSE(map[kAutofillId_].current.IsValid()); |
| + EXPECT_FALSE(map[kAutofillId_].expected.IsValid()); |
| EXPECT_EQ(15, map[kBookmarksId_].version); |
| + EXPECT_EQ("hello", map[kBookmarksId_].payload); |
| + EXPECT_FALSE(map[kBookmarksId_].current.IsValid()); |
| + EXPECT_FALSE(map[kBookmarksId_].expected.IsValid()); |
| + EXPECT_EQ(kint64min, map[kPreferencesId_].version); |
| + EXPECT_EQ(std::string(), map[kPreferencesId_].payload); |
| + EXPECT_THAT(map[kPreferencesId_].current, Eq(ack_handle_1)); |
| + EXPECT_THAT(map[kPreferencesId_].expected, Eq(ack_handle_2)); |
| + EXPECT_EQ(20, map[kAppNotificationsId_].version); |
| + EXPECT_EQ("world", map[kAppNotificationsId_].payload); |
| + EXPECT_THAT(map[kAppNotificationsId_].current, Eq(ack_handle_3)); |
| + EXPECT_THAT(map[kAppNotificationsId_].expected, Eq(ack_handle_4)); |
| } |
| // Tests for legacy deserialization code. |
| @@ -340,4 +391,78 @@ TEST_F(InvalidatorStorageTest, SetGetBootstrapData) { |
| EXPECT_EQ(mess, storage.GetBootstrapData()); |
| } |
| +// Test that we correctly generate ack handles, acknowledge them, and persist |
| +// them. |
| +TEST_F(InvalidatorStorageTest, GenerateAckHandlesAndAcknowledge) { |
| + InvalidatorStorage storage(&pref_service_); |
| + syncer::ObjectIdSet ids; |
| + InvalidationStateMap state_map; |
| + syncer::AckHandleMap ack_handle_map; |
| + syncer::AckHandleMap::const_iterator it; |
| + |
| + // Test that it works as expected if the key doesn't already exist in the map, |
| + // e.g. the first invalidation received for the object ID was not for a |
| + // specific version. |
| + ids.insert(kAutofillId_); |
| + storage.GenerateAckHandles( |
| + ids, base::MessageLoopProxy::current(), |
| + base::Bind(&GenerateAckHandlesTestHelper, &ack_handle_map)); |
| + loop_.RunUntilIdle(); |
| + EXPECT_EQ(1U, ack_handle_map.size()); |
| + it = ack_handle_map.find(kAutofillId_); |
| + ASSERT_NE(ack_handle_map.end(), it); |
| + EXPECT_TRUE(it->second.IsValid()); |
| + state_map[kAutofillId_].expected = it->second; |
| + EXPECT_EQ(state_map, storage.GetAllInvalidationStates()); |
| + |
| + storage.Acknowledge(kAutofillId_, it->second); |
| + state_map[kAutofillId_].current = it->second; |
| + EXPECT_EQ(state_map, storage.GetAllInvalidationStates()); |
| + |
| + ids.clear(); |
| + |
| + // Test that it works as expected if the key already exists. |
| + state_map[kBookmarksId_].version = 11; |
| + state_map[kBookmarksId_].payload = "hello"; |
| + storage.SetMaxVersionAndPayload(kBookmarksId_, 11, "hello"); |
| + EXPECT_EQ(state_map, storage.GetAllInvalidationStates()); |
| + ids.insert(kBookmarksId_); |
| + storage.GenerateAckHandles( |
| + ids, base::MessageLoopProxy::current(), |
| + base::Bind(&GenerateAckHandlesTestHelper, &ack_handle_map)); |
| + loop_.RunUntilIdle(); |
| + EXPECT_EQ(1U, ack_handle_map.size()); |
| + it = ack_handle_map.find(kBookmarksId_); |
| + ASSERT_NE(ack_handle_map.end(), it); |
| + EXPECT_TRUE(it->second.IsValid()); |
| + state_map[kBookmarksId_].expected = it->second; |
| + EXPECT_EQ(state_map, storage.GetAllInvalidationStates()); |
| + |
| + storage.Acknowledge(kBookmarksId_, it->second); |
| + state_map[kBookmarksId_].current = it->second; |
| + EXPECT_EQ(state_map, storage.GetAllInvalidationStates()); |
| + |
| + // Finally, test that the ack handles are updated if we're asked to generate |
| + // another ack handle for the same object ID. |
| + state_map[kBookmarksId_].version = 12; |
| + state_map[kBookmarksId_].payload = "world"; |
| + storage.SetMaxVersionAndPayload(kBookmarksId_, 12, "world"); |
| + EXPECT_EQ(state_map, storage.GetAllInvalidationStates()); |
| + ids.insert(kBookmarksId_); |
| + storage.GenerateAckHandles( |
| + ids, base::MessageLoopProxy::current(), |
| + base::Bind(&GenerateAckHandlesTestHelper, &ack_handle_map)); |
| + loop_.RunUntilIdle(); |
| + EXPECT_EQ(1U, ack_handle_map.size()); |
| + it = ack_handle_map.find(kBookmarksId_); |
| + ASSERT_NE(ack_handle_map.end(), it); |
| + EXPECT_TRUE(it->second.IsValid()); |
| + state_map[kBookmarksId_].expected = it->second; |
| + EXPECT_EQ(state_map, storage.GetAllInvalidationStates()); |
| + |
| + storage.Acknowledge(kBookmarksId_, it->second); |
| + state_map[kBookmarksId_].current = it->second; |
| + EXPECT_EQ(state_map, storage.GetAllInvalidationStates()); |
| +} |
| + |
| } // namespace browser_sync |