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..022d6dc143677499ec865e7081f3c0808811620e 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,92 @@ std::string CreateNextAppId(const std::string& app_id) { |
return next_app_id; |
} |
+constexpr char kUnset[] = "__unset__"; |
+constexpr char kDefault[] = "__default__"; |
+ |
+// BAD STYLE ALERT: using const instead of constexpr in order to initialize |
+// with results of crx_file::id_util::GenerateId(). |
+const std::string kInvalidOrdinalsId = GenerateId("invalid_ordinals"); |
xiyuan
2017/06/23 17:11:34
std::string is not allowed for global variable and
stevenjb
2017/06/23 19:46:05
e.g.. these could be members of a helper struct an
rcui
2017/06/23 21:28:08
How about this - defining the constants as functio
rcui
2017/06/23 21:28:41
This is done in the newest patchset.
|
+const std::string kEmptyItemNameId = GenerateId("empty_item_name"); |
+const std::string kEmptyItemNameUnsetId = GenerateId("empty_item_name_unset"); |
+const std::string kEmptyParentId = GenerateId("empty_parent_id"); |
+const std::string kEmptyParentUnsetId = GenerateId("empty_parent_id_unset"); |
+const std::string kEmptyOrdinalsId = GenerateId("empty_ordinals"); |
+const std::string kEmptyOrdinalsUnsetId = GenerateId("empty_ordinals_unset"); |
+const std::string kDupeItemId = GenerateId("dupe_item_id"); |
+const std::string kParentId = 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 +167,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 +234,159 @@ 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); |
+ |
+ 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", 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); |
+ 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)); |
+} |