Chromium Code Reviews| Index: chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc |
| diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc |
| index e454e1b4cc618c35ae7170fc64a228a25fa86bd3..ca1ece8ea5c9fa867b46cee8a1c53138324fadea 100644 |
| --- a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc |
| +++ b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc |
| @@ -10,11 +10,18 @@ |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/crx_file/id_util.h" |
| +#include "components/sync/model/attachments/attachment_service_proxy_for_test.h" |
| +#include "components/sync/model/fake_sync_change_processor.h" |
| +#include "components/sync/model/sync_error_factory.h" |
| +#include "components/sync/model/sync_error_factory_mock.h" |
| +#include "components/sync/protocol/sync.pb.h" |
| #include "extensions/browser/extension_system.h" |
| #include "extensions/common/constants.h" |
| #include "ui/app_list/app_list_item.h" |
| #include "ui/app_list/app_list_model.h" |
| +using namespace crx_file::id_util; |
| + |
| namespace { |
| scoped_refptr<extensions::Extension> MakeApp( |
| @@ -46,6 +53,111 @@ std::string CreateNextAppId(const std::string& app_id) { |
| return next_app_id; |
| } |
| +constexpr char kUnset[] = "__unset__"; |
| +constexpr char kDefault[] = "__default__"; |
| + |
| +// These constants are defined as functions so their values can be derived via |
| +// function calls. The constant naming scheme is kept to maintain readability. |
| +const std::string kInvalidOrdinalsId() { |
|
khmel
2017/06/23 22:37:27
nit: it seems const here does not make sense. You
rcui
2017/06/24 00:19:10
Keeping the const, as it maintains consistency wit
khmel
2017/06/24 00:30:16
Acknowledged.
|
| + return GenerateId("invalid_ordinals"); |
| +} |
| +const std::string kEmptyItemNameId() { |
| + return GenerateId("empty_item_name"); |
| +} |
| +const std::string kEmptyItemNameUnsetId() { |
| + return GenerateId("empty_item_name_unset"); |
| +} |
| +const std::string kEmptyParentId() { |
| + return GenerateId("empty_parent_id"); |
| +} |
| +const std::string kEmptyParentUnsetId() { |
| + return GenerateId("empty_parent_id_unset"); |
| +} |
| +const std::string kEmptyOrdinalsId() { |
| + return GenerateId("empty_ordinals"); |
| +} |
| +const std::string kEmptyOrdinalsUnsetId() { |
| + return GenerateId("empty_ordinals_unset"); |
| +} |
| +const std::string kDupeItemId() { |
| + return GenerateId("dupe_item_id"); |
| +} |
| +const std::string kParentId() { |
| + return GenerateId("parent_id"); |
| +} |
| + |
| +syncer::SyncData CreateAppRemoteData(const std::string& id, |
| + const std::string& name, |
| + const std::string& parent_id, |
| + const std::string& item_ordinal, |
| + const std::string& item_pin_ordinal) { |
| + sync_pb::EntitySpecifics specifics; |
| + sync_pb::AppListSpecifics* app_list = specifics.mutable_app_list(); |
| + if (id != kUnset) |
| + app_list->set_item_id(id); |
| + app_list->set_item_type(sync_pb::AppListSpecifics_AppListItemType_TYPE_APP); |
| + if (name != kUnset) |
| + app_list->set_item_name(name); |
| + if (parent_id != kUnset) |
| + app_list->set_parent_id(parent_id); |
| + if (item_ordinal != kUnset) |
| + app_list->set_item_ordinal(item_ordinal); |
| + if (item_pin_ordinal != kUnset) |
| + app_list->set_item_pin_ordinal(item_pin_ordinal); |
| + |
| + return syncer::SyncData::CreateRemoteData( |
| + std::hash<std::string>{}(id), specifics, base::Time(), |
| + syncer::AttachmentIdList(), |
| + syncer::AttachmentServiceProxyForTest::Create()); |
| +} |
| + |
| +syncer::SyncDataList CreateBadAppRemoteData(const std::string& id) { |
| + syncer::SyncDataList sync_list; |
| + // Invalid item_ordinal and item_pin_ordinal. |
| + sync_list.push_back(CreateAppRemoteData( |
| + id == kDefault ? kInvalidOrdinalsId() : id, "item_name", kParentId(), |
| + "$$invalid_ordinal$$", "$$invalid_ordinal$$")); |
| + // Empty item name. |
| + sync_list.push_back( |
| + CreateAppRemoteData(id == kDefault ? kEmptyItemNameId() : id, "", |
| + kParentId(), "ordinal", "pinordinal")); |
| + sync_list.push_back( |
| + CreateAppRemoteData(id == kDefault ? kEmptyItemNameUnsetId() : id, kUnset, |
| + kParentId(), "ordinal", "pinordinal")); |
| + // Empty parent ID. |
| + sync_list.push_back( |
| + CreateAppRemoteData(id == kDefault ? kEmptyParentId() : id, "item_name", |
| + "", "ordinal", "pinordinal")); |
| + sync_list.push_back( |
| + CreateAppRemoteData(id == kDefault ? kEmptyParentUnsetId() : id, |
| + "item_name", kUnset, "ordinal", "pinordinal")); |
| + // Empty item_ordinal and item_pin_ordinal. |
| + sync_list.push_back( |
| + CreateAppRemoteData(id == kDefault ? kEmptyOrdinalsId() : id, "item_name", |
| + kParentId(), "", "")); |
| + sync_list.push_back( |
| + CreateAppRemoteData(id == kDefault ? kEmptyOrdinalsUnsetId() : id, |
| + "item_name", kParentId(), kUnset, kUnset)); |
| + // Duplicate item_id. |
| + sync_list.push_back(CreateAppRemoteData(id == kDefault ? kDupeItemId() : id, |
| + "item_name", kParentId(), "ordinal", |
| + "pinordinal")); |
| + sync_list.push_back(CreateAppRemoteData(id == kDefault ? kDupeItemId() : id, |
| + "item_name_dupe", kParentId(), |
| + "ordinal", "pinordinal")); |
| + // Empty item_id. |
| + sync_list.push_back(CreateAppRemoteData("", "item_name", kParentId(), |
| + "ordinal", "pinordinal")); |
| + sync_list.push_back(CreateAppRemoteData(kUnset, "item_name", kParentId(), |
| + "ordinal", "pinordinal")); |
| + // All fields empty. |
| + sync_list.push_back(CreateAppRemoteData("", "", "", "", "")); |
| + sync_list.push_back( |
| + CreateAppRemoteData(kUnset, kUnset, kUnset, kUnset, kUnset)); |
| + |
| + return sync_list; |
| +} |
| + |
| } // namespace |
| class AppListSyncableServiceTest : public AppListTestBase { |
| @@ -74,6 +186,16 @@ class AppListSyncableServiceTest : public AppListTestBase { |
| return app_list_syncable_service_->GetModel(); |
| } |
| + const app_list::AppListSyncableService::SyncItem* GetSyncItem( |
| + const std::string& id) const { |
| + return app_list_syncable_service_->GetSyncItem(id); |
| + } |
| + |
| + protected: |
| + app_list::AppListSyncableService* app_list_syncable_service() { |
| + return app_list_syncable_service_.get(); |
| + } |
| + |
| private: |
| base::ScopedTempDir temp_dir_; |
| std::unique_ptr<app_list::AppListSyncableService> app_list_syncable_service_; |
| @@ -131,3 +253,161 @@ TEST_F(AppListSyncableServiceTest, OEMFolderForConflictingPos) { |
| EXPECT_EQ(some_app_index, web_store_app_index + 1); |
| EXPECT_EQ(oem_folder_index, web_store_app_index + 2); |
| } |
| + |
| +TEST_F(AppListSyncableServiceTest, InitialMerge) { |
| + const std::string kItemId1 = GenerateId("item_id1"); |
| + const std::string kItemId2 = GenerateId("item_id2"); |
| + |
| + syncer::SyncDataList sync_list; |
| + sync_list.push_back(CreateAppRemoteData(kItemId1, "item_name1", |
| + GenerateId("parent_id1"), "ordinal", |
| + "pinordinal")); |
| + sync_list.push_back(CreateAppRemoteData(kItemId2, "item_name2", |
| + GenerateId("parent_id2"), "ordinal", |
| + "pinordinal")); |
| + |
| + app_list_syncable_service()->MergeDataAndStartSyncing( |
| + syncer::APP_LIST, sync_list, |
| + base::MakeUnique<syncer::FakeSyncChangeProcessor>(), |
| + base::MakeUnique<syncer::SyncErrorFactoryMock>()); |
| + content::RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + ASSERT_TRUE(GetSyncItem(kItemId1)); |
| + EXPECT_EQ("item_name1", GetSyncItem(kItemId1)->item_name); |
| + EXPECT_EQ(GenerateId("parent_id1"), GetSyncItem(kItemId1)->parent_id); |
| + EXPECT_EQ("ordinal", GetSyncItem(kItemId1)->item_ordinal.ToDebugString()); |
| + EXPECT_EQ("pinordinal", |
| + GetSyncItem(kItemId1)->item_pin_ordinal.ToDebugString()); |
| + |
| + ASSERT_TRUE(GetSyncItem(kItemId2)); |
| + EXPECT_EQ("item_name2", GetSyncItem(kItemId2)->item_name); |
| + EXPECT_EQ(GenerateId("parent_id2"), GetSyncItem(kItemId2)->parent_id); |
| + EXPECT_EQ("ordinal", GetSyncItem(kItemId2)->item_ordinal.ToDebugString()); |
| + EXPECT_EQ("pinordinal", |
| + GetSyncItem(kItemId2)->item_pin_ordinal.ToDebugString()); |
| +} |
| + |
| +TEST_F(AppListSyncableServiceTest, InitialMerge_BadData) { |
| + syncer::SyncDataList sync_list = CreateBadAppRemoteData(kDefault); |
|
khmel
2017/06/23 22:37:27
nit: const syncer::...
rcui
2017/06/24 00:19:10
Done.
|
| + |
| + app_list_syncable_service()->MergeDataAndStartSyncing( |
| + syncer::APP_LIST, sync_list, |
| + base::MakeUnique<syncer::FakeSyncChangeProcessor>(), |
| + base::MakeUnique<syncer::SyncErrorFactoryMock>()); |
| + content::RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + // Invalid item_ordinal and item_pin_ordinal. |
| + ASSERT_TRUE(GetSyncItem(kInvalidOrdinalsId())); |
| + EXPECT_EQ("n", |
|
khmel
2017/06/23 22:37:27
nit: It is not clear that "n" represents initial v
rcui
2017/06/24 00:19:10
With tests, I think it's good to be as literal as
khmel
2017/06/24 00:30:16
Acknowledged.
|
| + GetSyncItem(kInvalidOrdinalsId())->item_ordinal.ToDebugString()); |
| + EXPECT_EQ( |
| + "INVALID[$$invalid_ordinal$$]", |
| + GetSyncItem(kInvalidOrdinalsId())->item_pin_ordinal.ToDebugString()); |
| + |
| + // Empty item name. |
| + ASSERT_TRUE(GetSyncItem(kEmptyItemNameId())); |
| + EXPECT_EQ("", GetSyncItem(kEmptyItemNameId())->item_name); |
| + EXPECT_TRUE(GetSyncItem(kEmptyItemNameUnsetId())); |
| + EXPECT_EQ("", GetSyncItem(kEmptyItemNameUnsetId())->item_name); |
| + |
| + // Empty parent ID. |
| + ASSERT_TRUE(GetSyncItem(kEmptyParentId())); |
| + EXPECT_EQ("", GetSyncItem(kEmptyParentId())->parent_id); |
| + EXPECT_TRUE(GetSyncItem(kEmptyParentUnsetId())); |
| + EXPECT_EQ("", GetSyncItem(kEmptyParentUnsetId())->parent_id); |
| + |
| + // Empty item_ordinal and item_pin_ordinal. |
| + ASSERT_TRUE(GetSyncItem(kEmptyOrdinalsId())); |
| + EXPECT_EQ("n", GetSyncItem(kEmptyOrdinalsId())->item_ordinal.ToDebugString()); |
| + EXPECT_EQ("INVALID[]", |
| + GetSyncItem(kEmptyOrdinalsId())->item_pin_ordinal.ToDebugString()); |
| + ASSERT_TRUE(GetSyncItem(kEmptyOrdinalsUnsetId())); |
| + EXPECT_EQ("n", |
| + GetSyncItem(kEmptyOrdinalsUnsetId())->item_ordinal.ToDebugString()); |
| + EXPECT_EQ( |
| + "INVALID[]", |
| + GetSyncItem(kEmptyOrdinalsUnsetId())->item_pin_ordinal.ToDebugString()); |
| + |
| + // Duplicate item_id overrides previous. |
| + ASSERT_TRUE(GetSyncItem(kDupeItemId())); |
| + EXPECT_EQ("item_name_dupe", GetSyncItem(kDupeItemId())->item_name); |
| +} |
| + |
| +TEST_F(AppListSyncableServiceTest, InitialMergeAndUpdate) { |
| + const std::string kItemId1 = GenerateId("item_id1"); |
| + const std::string kItemId2 = GenerateId("item_id2"); |
| + |
| + syncer::SyncDataList sync_list; |
| + sync_list.push_back(CreateAppRemoteData(kItemId1, "item_name1", kParentId(), |
| + "ordinal", "pinordinal")); |
| + sync_list.push_back(CreateAppRemoteData(kItemId2, "item_name2", kParentId(), |
| + "ordinal", "pinordinal")); |
| + |
| + app_list_syncable_service()->MergeDataAndStartSyncing( |
| + syncer::APP_LIST, sync_list, |
| + base::MakeUnique<syncer::FakeSyncChangeProcessor>(), |
| + base::MakeUnique<syncer::SyncErrorFactoryMock>()); |
| + content::RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + ASSERT_TRUE(GetSyncItem(kItemId1)); |
| + ASSERT_TRUE(GetSyncItem(kItemId2)); |
| + |
| + syncer::SyncChangeList change_list; |
| + change_list.push_back(syncer::SyncChange( |
| + FROM_HERE, syncer::SyncChange::ACTION_UPDATE, |
| + CreateAppRemoteData(kItemId1, "item_name1x", GenerateId("parent_id1x"), |
| + "ordinalx", "pinordinalx"))); |
| + change_list.push_back(syncer::SyncChange( |
| + FROM_HERE, syncer::SyncChange::ACTION_UPDATE, |
| + CreateAppRemoteData(kItemId2, "item_name2x", GenerateId("parent_id2x"), |
| + "ordinalx", "pinordinalx"))); |
| + |
| + app_list_syncable_service()->ProcessSyncChanges(tracked_objects::Location(), |
| + change_list); |
| + content::RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + ASSERT_TRUE(GetSyncItem(kItemId1)); |
| + EXPECT_EQ("item_name1x", GetSyncItem(kItemId1)->item_name); |
|
khmel
2017/06/23 22:37:27
nit: It seems you frequently use this pattern. If
rcui
2017/06/24 00:19:10
I went ahead and tried it, and the issue with this
khmel
2017/06/24 00:30:16
Usually this is not a problem.
For example: https:
rcui
2017/06/24 01:01:54
It does seem like it'll make tests harder to maint
|
| + EXPECT_EQ(GenerateId("parent_id1x"), GetSyncItem(kItemId1)->parent_id); |
| + EXPECT_EQ("ordinalx", GetSyncItem(kItemId1)->item_ordinal.ToDebugString()); |
| + EXPECT_EQ("pinordinalx", |
| + GetSyncItem(kItemId1)->item_pin_ordinal.ToDebugString()); |
| + |
| + ASSERT_TRUE(GetSyncItem(kItemId2)); |
| + EXPECT_EQ("item_name2x", GetSyncItem(kItemId2)->item_name); |
| + EXPECT_EQ(GenerateId("parent_id2x"), GetSyncItem(kItemId2)->parent_id); |
| + EXPECT_EQ("ordinalx", GetSyncItem(kItemId2)->item_ordinal.ToDebugString()); |
| + EXPECT_EQ("pinordinalx", |
| + GetSyncItem(kItemId2)->item_pin_ordinal.ToDebugString()); |
| +} |
| + |
| +TEST_F(AppListSyncableServiceTest, InitialMergeAndUpdate_BadData) { |
| + const std::string kItemId = GenerateId("item_id"); |
| + |
| + syncer::SyncDataList sync_list; |
| + sync_list.push_back(CreateAppRemoteData(kItemId, "item_name", kParentId(), |
| + "ordinal", "pinordinal")); |
| + |
| + app_list_syncable_service()->MergeDataAndStartSyncing( |
| + syncer::APP_LIST, sync_list, |
| + base::MakeUnique<syncer::FakeSyncChangeProcessor>(), |
| + base::MakeUnique<syncer::SyncErrorFactoryMock>()); |
| + content::RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + ASSERT_TRUE(GetSyncItem(kItemId)); |
| + |
| + syncer::SyncChangeList change_list; |
| + syncer::SyncDataList update_list = CreateBadAppRemoteData(kItemId); |
| + for (syncer::SyncDataList::const_iterator iter = update_list.begin(); |
| + iter != update_list.end(); ++iter) { |
| + change_list.push_back(syncer::SyncChange( |
| + FROM_HERE, syncer::SyncChange::ACTION_UPDATE, *iter)); |
| + } |
| + |
| + // Validate items with bad data are processed without crashing. |
| + app_list_syncable_service()->ProcessSyncChanges(tracked_objects::Location(), |
| + change_list); |
| + content::RunAllBlockingPoolTasksUntilIdle(); |
| + |
| + ASSERT_TRUE(GetSyncItem(kItemId)); |
|
khmel
2017/06/23 22:37:27
nit: it would be nice to check that sync item was
rcui
2017/06/24 00:19:11
Given the type of bad data we're using, the sync i
khmel
2017/06/24 00:30:16
Up to you, I just wanted to see the use case when
rcui
2017/06/24 01:01:54
Acknowledged.
|
| +} |