Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "base/macros.h" | 5 #include "base/macros.h" | 
| 6 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" | 6 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" | 
| 7 #include "chrome/browser/sync/test/integration/sync_test.h" | 7 #include "chrome/browser/sync/test/integration/sync_test.h" | 
| 8 #include "components/browser_sync/profile_sync_service.h" | 8 #include "components/browser_sync/profile_sync_service.h" | 
| 9 #include "components/sync/base/model_type.h" | 9 #include "components/sync/base/model_type.h" | 
| 10 #include "components/sync/base/sync_prefs.h" | |
| 10 #include "components/sync/driver/sync_driver_switches.h" | 11 #include "components/sync/driver/sync_driver_switches.h" | 
| 11 #include "components/sync/syncable/read_node.h" | 12 #include "components/sync/syncable/read_node.h" | 
| 12 #include "components/sync/syncable/read_transaction.h" | 13 #include "components/sync/syncable/read_transaction.h" | 
| 13 | 14 | 
| 14 // This file contains tests that exercise enabling and disabling data | 15 using base::FeatureList; | 
| 15 // types. | 16 using syncer::ModelType; | 
| 17 using syncer::ModelTypeSet; | |
| 18 using syncer::ModelTypeToString; | |
| 19 using syncer::ProxyTypes; | |
| 20 using syncer::SyncPrefs; | |
| 21 using syncer::UserSelectableTypes; | |
| 22 using syncer::UserShare; | |
| 16 | 23 | 
| 17 namespace { | 24 namespace { | 
| 18 | 25 | 
| 19 using base::FeatureList; | 26 bool DoesTopLevelNodeExist(UserShare* user_share, ModelType type) { | 
| 20 using syncer::ModelTypeSet; | 27 syncer::ReadTransaction trans(FROM_HERE, user_share); | 
| 28 syncer::ReadNode node(&trans); | |
| 29 return node.InitTypeRoot(type) == syncer::BaseNode::INIT_OK; | |
| 30 } | |
| 21 | 31 | 
| 22 class EnableDisableSingleClientTest : public SyncTest { | 32 void VerifyExistence(UserShare* user_share, bool exists, ModelType type) { | 
| 23 public: | 33 EXPECT_EQ(exists, DoesTopLevelNodeExist(user_share, type)) | 
| 24 EnableDisableSingleClientTest() : SyncTest(SINGLE_CLIENT) {} | 34 << ModelTypeToString(type); | 
| 25 ~EnableDisableSingleClientTest() override {} | 35 } | 
| 26 | 36 | 
| 27 // Don't use self-notifications as they can trigger additional sync cycles. | 37 void VerifyExistence(UserShare* user_share, | 
| 
 
Patrick Noland
2017/02/02 22:11:37
Can you give the VerifyExistence functions more de
 
skym
2017/02/02 23:37:52
Done.
 
 | |
| 28 bool TestUsesSelfNotifications() override { return false; } | 38 bool exists, | 
| 29 | 39 ModelType grouped, | 
| 30 private: | 40 ModelType selectable) { | 
| 31 DISALLOW_COPY_AND_ASSIGN(EnableDisableSingleClientTest); | 41 EXPECT_EQ(exists, DoesTopLevelNodeExist(user_share, grouped)) | 
| 32 }; | 42 << ModelTypeToString(selectable) << "->" << ModelTypeToString(grouped); | 
| 33 | |
| 34 bool DoesTopLevelNodeExist(syncer::UserShare* user_share, | |
| 35 syncer::ModelType type) { | |
| 36 syncer::ReadTransaction trans(FROM_HERE, user_share); | |
| 37 syncer::ReadNode node(&trans); | |
| 38 return node.InitTypeRoot(type) == syncer::BaseNode::INIT_OK; | |
| 39 } | 43 } | 
| 40 | 44 | 
| 41 bool IsUnready(const syncer::DataTypeStatusTable& data_type_status_table, | 45 bool IsUnready(const syncer::DataTypeStatusTable& data_type_status_table, | 
| 42 syncer::ModelType type) { | 46 ModelType type) { | 
| 43 return data_type_status_table.GetUnreadyErrorTypes().Has(type); | 47 return data_type_status_table.GetUnreadyErrorTypes().Has(type); | 
| 44 } | 48 } | 
| 45 | 49 | 
| 46 // The current approach this test class takes is to examine the Directory and | 50 // The current approach this test class takes is to examine the Directory and | 
| 47 // check for root nodes to see if a type is currently enabled. While this works | 51 // check for root nodes to see if a type is currently enabled. While this works | 
| 48 // for things in the directory, it does not work for USS types. USS does not | 52 // for things in the directory, it does not work for USS types. USS does not | 
| 49 // have any general data access mechanism, at least yet. Until that exists, | 53 // have any general data access mechanism, at least yet. Until that exists, | 
| 50 // simply omit types that may be USS from these cases. | 54 // simply omit types that may be USS from these cases. | 
| 51 ModelTypeSet UnifiedSyncServiceTypes() { | 55 ModelTypeSet UnifiedSyncServiceTypes() { | 
| 52 ModelTypeSet set; | 56 ModelTypeSet set; | 
| 53 if (FeatureList::IsEnabled(switches::kSyncUSSDeviceInfo)) { | 57 if (FeatureList::IsEnabled(switches::kSyncUSSDeviceInfo)) { | 
| 54 set.Put(syncer::DEVICE_INFO); | 58 set.Put(syncer::DEVICE_INFO); | 
| 55 } | 59 } | 
| 60 // All new types should be USS. This logic is fragile to reordering ModelType. | |
| 61 for (int typeInt = syncer::PRINTERS; typeInt < syncer::FIRST_PROXY_TYPE; | |
| 
 
Patrick Noland
2017/02/02 22:11:37
Should we alias PRINTERS to something analogous to
 
skym
2017/02/02 23:37:52
How about I expand the comment here to include tha
 
 | |
| 62 typeInt++) { | |
| 63 set.Put(static_cast<ModelType>(typeInt)); | |
| 64 } | |
| 56 return set; | 65 return set; | 
| 57 } | 66 } | 
| 58 | 67 | 
| 68 // Some groups show up in multiple groups. This means that there are at least | |
| 
 
Patrick Noland
2017/02/02 22:11:37
Do you mean that some types show up in multiple gr
 
Patrick Noland
2017/02/02 22:11:37
I don't understand the phrase "at least user selec
 
skym
2017/02/02 23:37:52
You're correct, should be "...at least _two_ user
 
skym
2017/02/02 23:37:52
Yes, done.
 
 | |
| 69 // user selectable groups that will cause these types to become enabled. This | |
| 70 // affects our tests because we cannot assume that before enabling a multi type | |
| 71 // it will be disabled, because the other selectable type(s) could already be | |
| 72 // enabling it. And vice versa for disabling. | |
| 73 ModelTypeSet MultiGroupTypes(const SyncPrefs& sync_prefs, | |
| 74 const ModelTypeSet& registered_types) { | |
| 75 const ModelTypeSet selectable_types = UserSelectableTypes(); | |
| 76 ModelTypeSet seen; | |
| 77 ModelTypeSet multi; | |
| 78 for (ModelTypeSet::Iterator si = selectable_types.First(); si.Good(); | |
| 79 si.Inc()) { | |
| 80 const ModelTypeSet grouped_types = | |
| 81 sync_prefs.ResolvePrefGroups(registered_types, ModelTypeSet(si.Get())); | |
| 82 for (ModelTypeSet::Iterator gi = grouped_types.First(); gi.Good(); | |
| 83 gi.Inc()) { | |
| 84 if (seen.Has(gi.Get())) { | |
| 85 multi.Put(gi.Get()); | |
| 86 } else { | |
| 87 seen.Put(gi.Get()); | |
| 88 } | |
| 89 } | |
| 90 } | |
| 91 return multi; | |
| 92 } | |
| 93 | |
| 94 // This test enables and disables types and verifies the type is sufficiently | |
| 95 // affected by checking for existence of a root node. | |
| 96 class EnableDisableSingleClientTest : public SyncTest { | |
| 97 public: | |
| 98 EnableDisableSingleClientTest() : SyncTest(SINGLE_CLIENT) {} | |
| 99 ~EnableDisableSingleClientTest() override {} | |
| 100 | |
| 101 // Don't use self-notifications as they can trigger additional sync cycles. | |
| 102 bool TestUsesSelfNotifications() override { return false; } | |
| 103 | |
| 104 private: | |
| 105 DISALLOW_COPY_AND_ASSIGN(EnableDisableSingleClientTest); | |
| 106 }; | |
| 107 | |
| 59 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableOneAtATime) { | 108 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableOneAtATime) { | 
| 60 ASSERT_TRUE(SetupClients()); | 109 ASSERT_TRUE(SetupClients()); | 
| 61 | 110 SyncPrefs sync_prefs(GetProfile(0)->GetPrefs()); | 
| 62 // Setup sync with no enabled types. | 111 // Setup sync with no enabled types. | 
| 63 ASSERT_TRUE(GetClient(0)->SetupSync(ModelTypeSet())); | 112 ASSERT_TRUE(GetClient(0)->SetupSync(ModelTypeSet())); | 
| 64 | 113 UserShare* user_share = GetSyncService(0)->GetUserShare(); | 
| 65 syncer::UserShare* user_share = GetSyncService(0)->GetUserShare(); | |
| 66 const syncer::DataTypeStatusTable& data_type_status_table = | |
| 67 GetSyncService(0)->data_type_status_table(); | |
| 68 | 114 | 
| 69 const ModelTypeSet registered_types = | 115 const ModelTypeSet registered_types = | 
| 70 GetSyncService(0)->GetRegisteredDataTypes(); | 116 GetSyncService(0)->GetRegisteredDataTypes(); | 
| 71 const ModelTypeSet registered_directory_types = | 117 const ModelTypeSet multi_grouped_types = | 
| 72 Difference(registered_types, UnifiedSyncServiceTypes()); | 118 MultiGroupTypes(sync_prefs, registered_types); | 
| 73 const ModelTypeSet registered_directory_user_types = | 119 const ModelTypeSet selectable_types = | 
| 74 Intersection(registered_types, syncer::UserSelectableTypes()); | 120 Intersection(registered_types, UserSelectableTypes()); | 
| 75 for (ModelTypeSet::Iterator it = registered_directory_user_types.First(); | 121 for (ModelTypeSet::Iterator si = selectable_types.First(); si.Good(); | 
| 76 it.Good(); it.Inc()) { | 122 si.Inc()) { | 
| 77 ASSERT_TRUE(GetClient(0)->EnableSyncForDatatype(it.Get())); | 123 const ModelTypeSet grouped_types = | 
| 78 | 124 Difference(Difference(sync_prefs.ResolvePrefGroups( | 
| 79 // AUTOFILL_PROFILE is lumped together with AUTOFILL. | 125 registered_types, ModelTypeSet(si.Get())), | 
| 80 // SESSIONS is lumped together with PROXY_TABS and | 126 ProxyTypes()), | 
| 81 // HISTORY_DELETE_DIRECTIVES. | 127 UnifiedSyncServiceTypes()); | 
| 82 // Favicons are lumped together with PROXY_TABS and | 128 const ModelTypeSet single_grouped_types = | 
| 83 // HISTORY_DELETE_DIRECTIVES. | 129 Difference(grouped_types, multi_grouped_types); | 
| 84 if (it.Get() == syncer::AUTOFILL_PROFILE || it.Get() == syncer::SESSIONS) { | 130 for (ModelTypeSet::Iterator sgi = single_grouped_types.First(); sgi.Good(); | 
| 85 continue; | 131 sgi.Inc()) { | 
| 132 VerifyExistence(user_share, false, sgi.Get(), si.Get()); | |
| 86 } | 133 } | 
| 87 | 134 | 
| 88 if (!syncer::ProxyTypes().Has(it.Get())) { | 135 EXPECT_TRUE(GetClient(0)->EnableSyncForDatatype(si.Get())); | 
| 89 ASSERT_TRUE(DoesTopLevelNodeExist(user_share, it.Get()) || | |
| 90 IsUnready(data_type_status_table, it.Get())) | |
| 91 << syncer::ModelTypeToString(it.Get()); | |
| 92 } | |
| 93 | 136 | 
| 94 // AUTOFILL_PROFILE is lumped together with AUTOFILL. | 137 for (ModelTypeSet::Iterator gi = grouped_types.First(); gi.Good(); | 
| 95 if (it.Get() == syncer::AUTOFILL) { | 138 gi.Inc()) { | 
| 96 ASSERT_TRUE(DoesTopLevelNodeExist(user_share, | 139 VerifyExistence(user_share, true, gi.Get(), si.Get()); | 
| 97 syncer::AUTOFILL_PROFILE)); | |
| 98 } else if (it.Get() == syncer::HISTORY_DELETE_DIRECTIVES || | |
| 99 it.Get() == syncer::PROXY_TABS) { | |
| 100 ASSERT_TRUE(DoesTopLevelNodeExist(user_share, | |
| 101 syncer::SESSIONS)); | |
| 102 } | 140 } | 
| 103 } | 141 } | 
| 104 } | 142 } | 
| 105 | 143 | 
| 106 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, DisableOneAtATime) { | 144 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, DisableOneAtATime) { | 
| 107 ASSERT_TRUE(SetupClients()); | 145 ASSERT_TRUE(SetupClients()); | 
| 108 | 146 SyncPrefs sync_prefs(GetProfile(0)->GetPrefs()); | 
| 109 // Setup sync with no disabled types. | 147 // Setup sync with no disabled types. | 
| 110 ASSERT_TRUE(GetClient(0)->SetupSync()); | 148 ASSERT_TRUE(GetClient(0)->SetupSync()); | 
| 149 UserShare* user_share = GetSyncService(0)->GetUserShare(); | |
| 150 const syncer::DataTypeStatusTable& data_type_status_table = | |
| 151 GetSyncService(0)->data_type_status_table(); | |
| 111 | 152 | 
| 112 const ModelTypeSet registered_types = | 153 const ModelTypeSet registered_types = | 
| 113 GetSyncService(0)->GetRegisteredDataTypes(); | 154 GetSyncService(0)->GetRegisteredDataTypes(); | 
| 114 const ModelTypeSet registered_directory_types = | 155 const ModelTypeSet multi_grouped_types = | 
| 115 Difference(registered_types, UnifiedSyncServiceTypes()); | 156 MultiGroupTypes(sync_prefs, registered_types); | 
| 157 const ModelTypeSet registered_directory_types = Difference( | |
| 158 Difference(registered_types, UnifiedSyncServiceTypes()), ProxyTypes()); | |
| 159 // Make sure all top-level nodes exist first. | |
| 160 for (ModelTypeSet::Iterator rdi = registered_directory_types.First(); | |
| 161 rdi.Good(); rdi.Inc()) { | |
| 162 EXPECT_TRUE(DoesTopLevelNodeExist(user_share, rdi.Get()) || | |
| 163 IsUnready(data_type_status_table, rdi.Get())) | |
| 164 << ModelTypeToString(rdi.Get()); | |
| 165 } | |
| 116 | 166 | 
| 117 syncer::UserShare* user_share = GetSyncService(0)->GetUserShare(); | 167 const ModelTypeSet selectable_types = | 
| 168 Intersection(registered_types, UserSelectableTypes()); | |
| 169 for (ModelTypeSet::Iterator si = selectable_types.First(); si.Good(); | |
| 170 si.Inc()) { | |
| 171 const ModelTypeSet grouped_types = | |
| 172 Difference(Difference(sync_prefs.ResolvePrefGroups( | |
| 173 registered_types, ModelTypeSet(si.Get())), | |
| 174 ProxyTypes()), | |
| 175 UnifiedSyncServiceTypes()); | |
| 176 for (ModelTypeSet::Iterator gi = grouped_types.First(); gi.Good(); | |
| 177 gi.Inc()) { | |
| 178 VerifyExistence(user_share, true, gi.Get(), si.Get()); | |
| 179 } | |
| 118 | 180 | 
| 119 const syncer::DataTypeStatusTable& data_type_status_table = | 181 EXPECT_TRUE(GetClient(0)->DisableSyncForDatatype(si.Get())); | 
| 120 GetSyncService(0)->data_type_status_table(); | |
| 121 | 182 | 
| 122 // Make sure all top-level nodes exist first. | 183 const ModelTypeSet single_grouped_types = | 
| 
 
Patrick Noland
2017/02/02 22:11:37
Is the calculation of grouped, single_Grouped, and
 
skym
2017/02/02 23:37:52
I tried to simplify things. I'm not sure it helped
 
 | |
| 123 for (ModelTypeSet::Iterator it = registered_directory_types.First(); | 184 Difference(grouped_types, multi_grouped_types); | 
| 124 it.Good(); it.Inc()) { | 185 for (ModelTypeSet::Iterator sgi = single_grouped_types.First(); sgi.Good(); | 
| 125 if (!syncer::ProxyTypes().Has(it.Get())) { | 186 sgi.Inc()) { | 
| 126 ASSERT_TRUE(DoesTopLevelNodeExist(user_share, it.Get()) || | 187 VerifyExistence(user_share, false, sgi.Get(), si.Get()); | 
| 127 IsUnready(data_type_status_table, it.Get())); | |
| 128 } | 188 } | 
| 129 } | 189 } | 
| 130 | 190 | 
| 131 for (ModelTypeSet::Iterator it = registered_directory_types.First(); | 191 // Lastly make sure that all the multi grouped times are all gone, since we | 
| 132 it.Good(); it.Inc()) { | 192 // did not check these after disabling inside the above loop. | 
| 133 // SUPERVISED_USERS and SUPERVISED_USER_SHARED_SETTINGS are always synced. | 193 for (ModelTypeSet::Iterator mgi = multi_grouped_types.First(); mgi.Good(); | 
| 134 if (it.Get() == syncer::SUPERVISED_USERS || | 194 mgi.Inc()) { | 
| 135 it.Get() == syncer::SUPERVISED_USER_SHARED_SETTINGS || | 195 VerifyExistence(user_share, false, mgi.Get()); | 
| 136 it.Get() == syncer::SYNCED_NOTIFICATIONS || | |
| 137 it.Get() == syncer::SYNCED_NOTIFICATION_APP_INFO) | |
| 138 continue; | |
| 139 | |
| 140 // Device info cannot be disabled. | |
| 141 if (it.Get() == syncer::DEVICE_INFO) | |
| 142 continue; | |
| 143 | |
| 144 ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(it.Get())); | |
| 145 | |
| 146 // AUTOFILL_PROFILE is lumped together with AUTOFILL. | |
| 147 // SESSIONS is lumped together with PROXY_TABS and TYPED_URLS. | |
| 148 // HISTORY_DELETE_DIRECTIVES is lumped together with TYPED_URLS. | |
| 149 // PRIORITY_PREFERENCES is lumped together with PREFERENCES. | |
| 150 // Favicons are lumped together with PROXY_TABS and | |
| 151 // HISTORY_DELETE_DIRECTIVES. | |
| 152 if (it.Get() == syncer::AUTOFILL_PROFILE || | |
| 153 it.Get() == syncer::SESSIONS || | |
| 154 it.Get() == syncer::HISTORY_DELETE_DIRECTIVES || | |
| 155 it.Get() == syncer::PRIORITY_PREFERENCES || | |
| 156 it.Get() == syncer::FAVICON_IMAGES || | |
| 157 it.Get() == syncer::FAVICON_TRACKING) { | |
| 158 continue; | |
| 159 } | |
| 160 | |
| 161 syncer::UserShare* user_share = | |
| 162 GetSyncService(0)->GetUserShare(); | |
| 163 | |
| 164 ASSERT_FALSE(DoesTopLevelNodeExist(user_share, it.Get())) | |
| 165 << syncer::ModelTypeToString(it.Get()); | |
| 166 | |
| 167 if (it.Get() == syncer::AUTOFILL) { | |
| 168 // AUTOFILL_PROFILE is lumped together with AUTOFILL. | |
| 169 ASSERT_FALSE(DoesTopLevelNodeExist(user_share, syncer::AUTOFILL_PROFILE)); | |
| 170 } else if (it.Get() == syncer::TYPED_URLS) { | |
| 171 ASSERT_FALSE(DoesTopLevelNodeExist(user_share, | |
| 172 syncer::HISTORY_DELETE_DIRECTIVES)); | |
| 173 // SESSIONS should be enabled only if PROXY_TABS is. | |
| 174 ASSERT_EQ(GetClient(0)->IsTypePreferred(syncer::PROXY_TABS), | |
| 175 DoesTopLevelNodeExist(user_share, syncer::SESSIONS)); | |
| 176 } else if (it.Get() == syncer::PROXY_TABS) { | |
| 177 // SESSIONS should be enabled only if TYPED_URLS is. | |
| 178 ASSERT_EQ(GetClient(0)->IsTypePreferred(syncer::TYPED_URLS), | |
| 179 DoesTopLevelNodeExist(user_share, syncer::SESSIONS)); | |
| 180 } else if (it.Get() == syncer::PREFERENCES) { | |
| 181 ASSERT_FALSE(DoesTopLevelNodeExist(user_share, | |
| 182 syncer::PRIORITY_PREFERENCES)); | |
| 183 } | |
| 184 } | 196 } | 
| 185 } | 197 } | 
| 186 | 198 | 
| 187 } // namespace | 199 } // namespace | 
| OLD | NEW |