1 // Copyright 2014 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 #include "base/strings/string_number_conversions.h" 6 #include "google_apis/gcm/engine/gservices_settings.h" 7 #include "google_apis/gcm/engine/registration_info.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 namespace gcm { 11 12 namespace { 13 14 const int64 kAlternativeCheckinInterval = 16 * 60 * 60; 15 const char kAlternativeCheckinURL[] = "http://alternative.url/checkin"; 16 const char kAlternativeMCSHostname[] = "alternative.gcm.host"; 17 const int kAlternativeMCSSecurePort = 7777; 18 const char kAlternativeRegistrationURL[] = 19 "http://alternative.url/registration"; 20 21 const int64 kDefaultCheckinInterval = 2 * 24 * 60 * 60; // seconds = 2 days. 22 const char kDefaultCheckinURL[] = "https://android.clients.google.com/checkin"; 23 const char kDefaultRegistrationURL[] = 24 "https://android.clients.google.com/c2dm/register3"; 25 const char kDefaultSettingsDigest[] = 26 "1-da39a3ee5e6b4b0d3255bfef95601890afd80709"; 27 const char kAlternativeSettingsDigest[] = 28 "1-7da4aa4eb38a8bd3e330e3751cc0899924499134"; 29 30 void AddSettingsToResponse( 31 checkin_proto::AndroidCheckinResponse& checkin_response, 32 const GServicesSettings::SettingsMap& settings, 33 bool settings_diff) { 34 for (GServicesSettings::SettingsMap::const_iterator iter = settings.begin(); 35 iter != settings.end(); 36 ++iter) { 37 checkin_proto::GservicesSetting* setting = checkin_response.add_setting(); 38 setting->set_name(iter->first); 39 setting->set_value(iter->second); 40 } 41 checkin_response.set_settings_diff(settings_diff); 42 } 43 44 } // namespace 45 46 class GServicesSettingsTest : public testing::Test { 47 public: 48 GServicesSettingsTest(); 49 virtual ~GServicesSettingsTest(); 50 51 void CheckAllSetToDefault(); 52 53 GServicesSettings& settings() { 54 return gserivces_settings_; 55 } 56 57 private: 58 GServicesSettings gserivces_settings_; 59 }; 60 61 GServicesSettingsTest::GServicesSettingsTest() 62 : gserivces_settings_() { 63 } 64 65 GServicesSettingsTest::~GServicesSettingsTest() {} 66 67 void GServicesSettingsTest::CheckAllSetToDefault() { 68 EXPECT_EQ(base::TimeDelta::FromSeconds(kDefaultCheckinInterval), 69 settings().GetCheckinInterval()); 70 EXPECT_EQ(GURL(kDefaultCheckinURL), settings().GetCheckinURL()); 71 EXPECT_EQ(GURL("https://mtalk.google.com:5228"), 72 settings().GetMCSMainEndpoint()); 73 EXPECT_EQ(GURL("https://mtalk.google.com:443"), 74 settings().GetMCSFallbackEndpoint()); 75 EXPECT_EQ(GURL(kDefaultRegistrationURL), settings().GetRegistrationURL()); 76 } 77 78 // Verifies default values of the G-services settings and settings digest. 79 TEST_F(GServicesSettingsTest, DefaultSettingsAndDigest) { 80 CheckAllSetToDefault(); 81 EXPECT_EQ(kDefaultSettingsDigest, settings().digest()); 82 EXPECT_EQ(kDefaultSettingsDigest, 83 GServicesSettings::CalculateDigest(settings().settings_map())); 84 } 85 86 // Verifies digest calculation for the sample provided by protocol owners. 87 TEST_F(GServicesSettingsTest, CalculateDigest) { 88 GServicesSettings::SettingsMap settings_map; 89 settings_map["android_id"] = "55XXXXXXXXXXXXXXXX0"; 90 settings_map["checkin_interval"] = "86400"; 91 settings_map["checkin_url"] = 92 "https://fake.address.google.com/canary/checkin"; 93 settings_map["chrome_device"] = "1"; 94 settings_map["device_country"] = "us"; 95 settings_map["gcm_hostname"] = "fake.address.google.com"; 96 settings_map["gcm_secure_port"] = "443"; 97 98 EXPECT_EQ("1-33381ccd1cf5791dc0e6dfa234266fa9f1259197", 99 GServicesSettings::CalculateDigest(settings_map)); 100 } 101 102 // Verifies that settings are not updated when load result is empty. 103 TEST_F(GServicesSettingsTest, UpdateFromEmptyLoadResult) { 104 GCMStore::LoadResult result; 105 result.gservices_digest = ""; 106 settings().UpdateFromLoadResult(result); 107 108 CheckAllSetToDefault(); 109 EXPECT_EQ(kDefaultSettingsDigest, settings().digest()); 110 } 111 112 // Verifies that settings are not when digest value does not match. 113 TEST_F(GServicesSettingsTest, UpdateFromLoadResultWithSettingMissing) { 114 GCMStore::LoadResult result; 115 result.gservices_settings["checkin_internval"] = "100000"; 116 result.gservices_digest = "digest_value"; 117 settings().UpdateFromLoadResult(result); 118 119 CheckAllSetToDefault(); 120 EXPECT_EQ(kDefaultSettingsDigest, settings().digest()); 121 } 122 123 // Verifies that the settings are set correctly based on the load result. 124 TEST_F(GServicesSettingsTest, UpdateFromLoadResult) { 125 GCMStore::LoadResult result; 126 result.gservices_settings["checkin_interval"] = 127 base::Int64ToString(kAlternativeCheckinInterval); 128 result.gservices_settings["checkin_url"] = kAlternativeCheckinURL; 129 result.gservices_settings["gcm_hostname"] = kAlternativeMCSHostname; 130 result.gservices_settings["gcm_secure_port"] = 131 base::IntToString(kAlternativeMCSSecurePort); 132 result.gservices_settings["gcm_registration_url"] = 133 kAlternativeRegistrationURL; 134 result.gservices_digest = kAlternativeSettingsDigest; 135 settings().UpdateFromLoadResult(result); 136 137 EXPECT_EQ(base::TimeDelta::FromSeconds(kAlternativeCheckinInterval), 138 settings().GetCheckinInterval()); 139 EXPECT_EQ(GURL(kAlternativeCheckinURL), settings().GetCheckinURL()); 140 EXPECT_EQ(GURL("https://alternative.gcm.host:7777"), 141 settings().GetMCSMainEndpoint()); 142 EXPECT_EQ(GURL("https://alternative.gcm.host:443"), 143 settings().GetMCSFallbackEndpoint()); 144 EXPECT_EQ(GURL(kAlternativeRegistrationURL), settings().GetRegistrationURL()); 145 EXPECT_EQ(GServicesSettings::CalculateDigest(result.gservices_settings), 146 settings().digest()); 147 } 148 149 // Verifies that the checkin interval is updated to minimum if the original 150 // value is less than minimum. 151 TEST_F(GServicesSettingsTest, CheckinResponseMinimumCheckinInterval) { 152 // Setting the checkin interval to less than minimum. 153 checkin_proto::AndroidCheckinResponse checkin_response; 154 GServicesSettings::SettingsMap new_settings; 155 new_settings["checkin_interval"] = "3600"; 156 AddSettingsToResponse(checkin_response, new_settings, false); 157 158 EXPECT_TRUE(settings().UpdateFromCheckinResponse(checkin_response)); 159 160 EXPECT_EQ(GServicesSettings::MinimumCheckinInterval(), 161 settings().GetCheckinInterval()); 162 EXPECT_EQ(GServicesSettings::CalculateDigest(new_settings), 163 settings().digest()); 164 } 165 166 // Verifies that default checkin interval can be selectively overwritten. 167 TEST_F(GServicesSettingsTest, CheckinResponseUpdateCheckinInterval) { 168 checkin_proto::AndroidCheckinResponse checkin_response; 169 GServicesSettings::SettingsMap new_settings; 170 new_settings["checkin_interval"] = "86400"; 171 AddSettingsToResponse(checkin_response, new_settings, false); 172 173 EXPECT_TRUE(settings().UpdateFromCheckinResponse(checkin_response)); 174 175 // Only the checkin interval was updated: 176 EXPECT_EQ(base::TimeDelta::FromSeconds(86400), 177 settings().GetCheckinInterval()); 178 179 // Other settings still set to default. 180 EXPECT_EQ(GURL("https://mtalk.google.com:5228"), 181 settings().GetMCSMainEndpoint()); 182 EXPECT_EQ(GURL("https://mtalk.google.com:443"), 183 settings().GetMCSFallbackEndpoint()); 184 EXPECT_EQ(GURL(kDefaultCheckinURL), settings().GetCheckinURL()); 185 EXPECT_EQ(GURL(kDefaultRegistrationURL), settings().GetRegistrationURL()); 186 187 EXPECT_EQ(GServicesSettings::CalculateDigest(new_settings), 188 settings().digest()); 189 } 190 191 // Verifies that default registration URL can be selectively overwritten. 192 TEST_F(GServicesSettingsTest, CheckinResponseUpdateRegistrationURL) { 193 checkin_proto::AndroidCheckinResponse checkin_response; 194 GServicesSettings::SettingsMap new_settings; 195 new_settings["gcm_registration_url"] = "https://new.registration.url"; 196 AddSettingsToResponse(checkin_response, new_settings, false); 197 198 EXPECT_TRUE(settings().UpdateFromCheckinResponse(checkin_response)); 199 200 // Only the registration URL was updated: 201 EXPECT_EQ(GURL("https://new.registration.url"), 202 settings().GetRegistrationURL()); 203 204 // Other settings still set to default. 205 EXPECT_EQ(base::TimeDelta::FromSeconds(kDefaultCheckinInterval), 206 settings().GetCheckinInterval()); 207 EXPECT_EQ(GURL("https://mtalk.google.com:5228"), 208 settings().GetMCSMainEndpoint()); 209 EXPECT_EQ(GURL("https://mtalk.google.com:443"), 210 settings().GetMCSFallbackEndpoint()); 211 EXPECT_EQ(GURL(kDefaultCheckinURL), settings().GetCheckinURL()); 212 213 EXPECT_EQ(GServicesSettings::CalculateDigest(new_settings), 214 settings().digest()); 215 } 216 217 // Verifies that default checkin URL can be selectively overwritten. 218 TEST_F(GServicesSettingsTest, CheckinResponseUpdateCheckinURL) { 219 checkin_proto::AndroidCheckinResponse checkin_response; 220 GServicesSettings::SettingsMap new_settings; 221 new_settings["checkin_url"] = "https://new.checkin.url"; 222 AddSettingsToResponse(checkin_response, new_settings, false); 223 224 EXPECT_TRUE(settings().UpdateFromCheckinResponse(checkin_response)); 225 226 // Only the checkin URL was updated: 227 EXPECT_EQ(GURL("https://new.checkin.url"), settings().GetCheckinURL()); 228 229 // Other settings still set to default. 230 EXPECT_EQ(base::TimeDelta::FromSeconds(kDefaultCheckinInterval), 231 settings().GetCheckinInterval()); 232 EXPECT_EQ(GURL("https://mtalk.google.com:5228"), 233 settings().GetMCSMainEndpoint()); 234 EXPECT_EQ(GURL("https://mtalk.google.com:443"), 235 settings().GetMCSFallbackEndpoint()); 236 EXPECT_EQ(GURL(kDefaultRegistrationURL), settings().GetRegistrationURL()); 237 238 EXPECT_EQ(GServicesSettings::CalculateDigest(new_settings), 239 settings().digest()); 240 } 241 242 // Verifies that default MCS hostname can be selectively overwritten. 243 TEST_F(GServicesSettingsTest, CheckinResponseUpdateMCSHostname) { 244 checkin_proto::AndroidCheckinResponse checkin_response; 245 GServicesSettings::SettingsMap new_settings; 246 new_settings["gcm_hostname"] = "new.gcm.hostname"; 247 AddSettingsToResponse(checkin_response, new_settings, false); 248 249 EXPECT_TRUE(settings().UpdateFromCheckinResponse(checkin_response)); 250 251 // Only the MCS endpoints were updated: 252 EXPECT_EQ(GURL("https://new.gcm.hostname:5228"), 253 settings().GetMCSMainEndpoint()); 254 EXPECT_EQ(GURL("https://new.gcm.hostname:443"), 255 settings().GetMCSFallbackEndpoint()); 256 257 // Other settings still set to default. 258 EXPECT_EQ(base::TimeDelta::FromSeconds(kDefaultCheckinInterval), 259 settings().GetCheckinInterval()); 260 EXPECT_EQ(GURL(kDefaultCheckinURL), settings().GetCheckinURL()); 261 EXPECT_EQ(GURL(kDefaultRegistrationURL), settings().GetRegistrationURL()); 262 263 EXPECT_EQ(GServicesSettings::CalculateDigest(new_settings), 264 settings().digest()); 265 } 266 267 // Verifies that default MCS secure port can be selectively overwritten. 268 TEST_F(GServicesSettingsTest, CheckinResponseUpdateMCSSecurePort) { 269 checkin_proto::AndroidCheckinResponse checkin_response; 270 GServicesSettings::SettingsMap new_settings; 271 new_settings["gcm_secure_port"] = "5229"; 272 AddSettingsToResponse(checkin_response, new_settings, false); 273 274 EXPECT_TRUE(settings().UpdateFromCheckinResponse(checkin_response)); 275 276 // Only the main MCS endpoint was updated: 277 EXPECT_EQ(GURL("https://mtalk.google.com:5229"), 278 settings().GetMCSMainEndpoint()); 279 280 // Other settings still set to default. 281 EXPECT_EQ(base::TimeDelta::FromSeconds(kDefaultCheckinInterval), 282 settings().GetCheckinInterval()); 283 EXPECT_EQ(GURL(kDefaultCheckinURL), settings().GetCheckinURL()); 284 EXPECT_EQ(GURL("https://mtalk.google.com:443"), 285 settings().GetMCSFallbackEndpoint()); 286 EXPECT_EQ(GURL(kDefaultRegistrationURL), settings().GetRegistrationURL()); 287 288 EXPECT_EQ(GServicesSettings::CalculateDigest(new_settings), 289 settings().digest()); 290 } 291 292 // Update from checkin response should also do incremental update for both cases 293 // where some settings are removed or added. 294 TEST_F(GServicesSettingsTest, UpdateFromCheckinResponseSettingsDiff) { 295 checkin_proto::AndroidCheckinResponse checkin_response; 296 297 // Only the new settings will be included in the response with settings diff. 298 GServicesSettings::SettingsMap settings_diff; 299 settings_diff["new_setting_1"] = "new_setting_1_value"; 300 settings_diff["new_setting_2"] = "new_setting_2_value"; 301 settings_diff["gcm_secure_port"] = "5229"; 302 303 // Full settings are necessary to calculate digest. 304 GServicesSettings::SettingsMap full_settings(settings_diff); 305 std::string digest = GServicesSettings::CalculateDigest(full_settings); 306 307 checkin_response.Clear(); 308 AddSettingsToResponse(checkin_response, settings_diff, true); 309 EXPECT_TRUE(settings().UpdateFromCheckinResponse(checkin_response)); 310 EXPECT_EQ(full_settings, settings().settings_map()); 311 // Default setting overwritten by settings diff. 312 EXPECT_EQ(GURL("https://mtalk.google.com:5229"), 313 settings().GetMCSMainEndpoint()); 314 315 // Setting up diff removing some of the values (including default setting). 316 settings_diff.clear(); 317 settings_diff["delete_new_setting_1"] = ""; 318 settings_diff["delete_gcm_secure_port"] = ""; 319 settings_diff["new_setting_3"] = "new_setting_3_value"; 320 321 // Updating full settings to calculate digest. 322 full_settings.erase(full_settings.find("new_setting_1")); 323 full_settings.erase(full_settings.find("gcm_secure_port")); 324 full_settings["new_setting_3"] = "new_setting_3_value"; 325 digest = GServicesSettings::CalculateDigest(full_settings); 326 327 checkin_response.Clear(); 328 AddSettingsToResponse(checkin_response, settings_diff, true); 329 EXPECT_TRUE(settings().UpdateFromCheckinResponse(checkin_response)); 330 EXPECT_EQ(full_settings, settings().settings_map()); 331 // Default setting back to norm. 332 EXPECT_EQ(GURL("https://mtalk.google.com:5228"), 333 settings().GetMCSMainEndpoint()); 334 } 335 336 } // namespace gcm 337