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 <string> 6 7 #include "google_apis/gcm/engine/checkin_request.h" 8 #include "google_apis/gcm/monitoring/fake_gcm_stats_recorder.h" 9 #include "google_apis/gcm/protocol/checkin.pb.h" 10 #include "net/base/backoff_entry.h" 11 #include "net/url_request/test_url_fetcher_factory.h" 12 #include "net/url_request/url_request_test_util.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 namespace gcm { 16 17 namespace { 18 19 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { 20 // Number of initial errors (in sequence) to ignore before applying 21 // exponential back-off rules. 22 // Explicitly set to 1 to skip the delay of the first Retry, as we are not 23 // trying to test the backoff itself, but rather the fact that retry happens. 24 1, 25 26 // Initial delay for exponential back-off in ms. 27 15000, // 15 seconds. 28 29 // Factor by which the waiting time will be multiplied. 30 2, 31 32 // Fuzzing percentage. ex: 10% will spread requests randomly 33 // between 90%-100% of the calculated time. 34 0.5, // 50%. 35 36 // Maximum amount of time we are willing to delay our request in ms. 37 1000 * 60 * 5, // 5 minutes. 38 39 // Time to keep an entry from being discarded even when it 40 // has no significant state, -1 to never discard. 41 -1, 42 43 // Don't use initial delay unless the last request was an error. 44 false, 45 }; 46 47 } 48 49 const uint64 kAndroidId = 42UL; 50 const uint64 kBlankAndroidId = 999999UL; 51 const uint64 kBlankSecurityToken = 999999UL; 52 const char kCheckinURL[] = "http://foo.bar/checkin"; 53 const char kChromeVersion[] = "Version String"; 54 const uint64 kSecurityToken = 77; 55 const char kSettingsDigest[] = "settings_digest"; 56 57 class CheckinRequestTest : public testing::Test { 58 public: 59 enum ResponseScenario { 60 VALID_RESPONSE, // Both android_id and security_token set in response. 61 MISSING_ANDROID_ID, // android_id is missing. 62 MISSING_SECURITY_TOKEN, // security_token is missing. 63 ANDROID_ID_IS_ZER0, // android_id is 0. 64 SECURITY_TOKEN_IS_ZERO // security_token is 0. 65 }; 66 67 CheckinRequestTest(); 68 virtual ~CheckinRequestTest(); 69 70 void FetcherCallback( 71 const checkin_proto::AndroidCheckinResponse& response); 72 73 void CreateRequest(uint64 android_id, uint64 security_token); 74 75 void SetResponseStatusAndString( 76 net::HttpStatusCode status_code, 77 const std::string& response_data); 78 79 void CompleteFetch(); 80 81 void SetResponse(ResponseScenario response_scenario); 82 83 protected: 84 bool callback_called_; 85 uint64 android_id_; 86 uint64 security_token_; 87 int checkin_device_type_; 88 base::MessageLoop message_loop_; 89 net::TestURLFetcherFactory url_fetcher_factory_; 90 scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_; 91 checkin_proto::ChromeBuildProto chrome_build_proto_; 92 scoped_ptr<CheckinRequest> request_; 93 FakeGCMStatsRecorder recorder_; 94 }; 95 96 CheckinRequestTest::CheckinRequestTest() 97 : callback_called_(false), 98 android_id_(kBlankAndroidId), 99 security_token_(kBlankSecurityToken), 100 checkin_device_type_(0), 101 url_request_context_getter_(new net::TestURLRequestContextGetter( 102 message_loop_.message_loop_proxy())) { 103 } 104 105 CheckinRequestTest::~CheckinRequestTest() {} 106 107 void CheckinRequestTest::FetcherCallback( 108 const checkin_proto::AndroidCheckinResponse& checkin_response) { 109 callback_called_ = true; 110 if (checkin_response.has_android_id()) 111 android_id_ = checkin_response.android_id(); 112 if (checkin_response.has_security_token()) 113 security_token_ = checkin_response.security_token(); 114 } 115 116 void CheckinRequestTest::CreateRequest(uint64 android_id, 117 uint64 security_token) { 118 // First setup a chrome_build protobuf. 119 chrome_build_proto_.set_platform( 120 checkin_proto::ChromeBuildProto::PLATFORM_LINUX); 121 chrome_build_proto_.set_channel( 122 checkin_proto::ChromeBuildProto::CHANNEL_CANARY); 123 chrome_build_proto_.set_chrome_version(kChromeVersion); 124 125 CheckinRequest::RequestInfo request_info( 126 android_id, 127 security_token, 128 kSettingsDigest, 129 chrome_build_proto_); 130 // Then create a request with that protobuf and specified android_id, 131 // security_token. 132 request_.reset(new CheckinRequest( 133 GURL(kCheckinURL), 134 request_info, 135 kDefaultBackoffPolicy, 136 base::Bind(&CheckinRequestTest::FetcherCallback, base::Unretained(this)), 137 url_request_context_getter_.get(), 138 &recorder_)); 139 140 // Setting android_id_ and security_token_ to blank value, not used elsewhere 141 // in the tests. 142 callback_called_ = false; 143 android_id_ = kBlankAndroidId; 144 security_token_ = kBlankSecurityToken; 145 } 146 147 void CheckinRequestTest::SetResponseStatusAndString( 148 net::HttpStatusCode status_code, 149 const std::string& response_data) { 150 net::TestURLFetcher* fetcher = 151 url_fetcher_factory_.GetFetcherByID(0); 152 ASSERT_TRUE(fetcher); 153 fetcher->set_response_code(status_code); 154 fetcher->SetResponseString(response_data); 155 } 156 157 void CheckinRequestTest::CompleteFetch() { 158 net::TestURLFetcher* fetcher = 159 url_fetcher_factory_.GetFetcherByID(0); 160 ASSERT_TRUE(fetcher); 161 fetcher->delegate()->OnURLFetchComplete(fetcher); 162 } 163 164 void CheckinRequestTest::SetResponse(ResponseScenario response_scenario) { 165 checkin_proto::AndroidCheckinResponse response; 166 response.set_stats_ok(true); 167 168 uint64 android_id = response_scenario == ANDROID_ID_IS_ZER0 ? 0 : kAndroidId; 169 uint64 security_token = 170 response_scenario == SECURITY_TOKEN_IS_ZERO ? 0 : kSecurityToken; 171 172 if (response_scenario != MISSING_ANDROID_ID) 173 response.set_android_id(android_id); 174 175 if (response_scenario != MISSING_SECURITY_TOKEN) 176 response.set_security_token(security_token); 177 178 std::string response_string; 179 response.SerializeToString(&response_string); 180 SetResponseStatusAndString(net::HTTP_OK, response_string); 181 } 182 183 TEST_F(CheckinRequestTest, FetcherDataAndURL) { 184 CreateRequest(kAndroidId, kSecurityToken); 185 request_->Start(); 186 187 // Get data sent by request. 188 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 189 ASSERT_TRUE(fetcher); 190 EXPECT_EQ(GURL(kCheckinURL), fetcher->GetOriginalURL()); 191 192 checkin_proto::AndroidCheckinRequest request_proto; 193 request_proto.ParseFromString(fetcher->upload_data()); 194 EXPECT_EQ(kAndroidId, static_cast<uint64>(request_proto.id())); 195 EXPECT_EQ(kSecurityToken, request_proto.security_token()); 196 EXPECT_EQ(chrome_build_proto_.platform(), 197 request_proto.checkin().chrome_build().platform()); 198 EXPECT_EQ(chrome_build_proto_.chrome_version(), 199 request_proto.checkin().chrome_build().chrome_version()); 200 EXPECT_EQ(chrome_build_proto_.channel(), 201 request_proto.checkin().chrome_build().channel()); 202 203 #if defined(CHROME_OS) 204 EXPECT_EQ(checkin_proto::DEVICE_CHROME_OS, request_proto.checkin().type()); 205 #else 206 EXPECT_EQ(checkin_proto::DEVICE_CHROME_BROWSER, 207 request_proto.checkin().type()); 208 #endif 209 210 EXPECT_EQ(kSettingsDigest, request_proto.digest()); 211 } 212 213 TEST_F(CheckinRequestTest, ResponseBodyEmpty) { 214 CreateRequest(0u, 0u); 215 request_->Start(); 216 217 SetResponseStatusAndString(net::HTTP_OK, std::string()); 218 CompleteFetch(); 219 220 EXPECT_FALSE(callback_called_); 221 222 SetResponse(VALID_RESPONSE); 223 CompleteFetch(); 224 225 EXPECT_TRUE(callback_called_); 226 EXPECT_EQ(kAndroidId, android_id_); 227 EXPECT_EQ(kSecurityToken, security_token_); 228 } 229 230 TEST_F(CheckinRequestTest, ResponseBodyCorrupted) { 231 CreateRequest(0u, 0u); 232 request_->Start(); 233 234 SetResponseStatusAndString(net::HTTP_OK, "Corrupted response body"); 235 CompleteFetch(); 236 237 EXPECT_FALSE(callback_called_); 238 239 SetResponse(VALID_RESPONSE); 240 CompleteFetch(); 241 242 EXPECT_TRUE(callback_called_); 243 EXPECT_EQ(kAndroidId, android_id_); 244 EXPECT_EQ(kSecurityToken, security_token_); 245 } 246 247 TEST_F(CheckinRequestTest, ResponseHttpStatusUnauthorized) { 248 CreateRequest(0u, 0u); 249 request_->Start(); 250 251 SetResponseStatusAndString(net::HTTP_UNAUTHORIZED, std::string()); 252 CompleteFetch(); 253 254 EXPECT_TRUE(callback_called_); 255 EXPECT_EQ(kBlankAndroidId, android_id_); 256 EXPECT_EQ(kBlankSecurityToken, security_token_); 257 } 258 259 TEST_F(CheckinRequestTest, ResponseHttpStatusBadRequest) { 260 CreateRequest(0u, 0u); 261 request_->Start(); 262 263 SetResponseStatusAndString(net::HTTP_BAD_REQUEST, std::string()); 264 CompleteFetch(); 265 266 EXPECT_TRUE(callback_called_); 267 EXPECT_EQ(kBlankAndroidId, android_id_); 268 EXPECT_EQ(kBlankSecurityToken, security_token_); 269 } 270 271 TEST_F(CheckinRequestTest, ResponseHttpStatusNotOK) { 272 CreateRequest(0u, 0u); 273 request_->Start(); 274 275 SetResponseStatusAndString(net::HTTP_INTERNAL_SERVER_ERROR, std::string()); 276 CompleteFetch(); 277 278 EXPECT_FALSE(callback_called_); 279 280 SetResponse(VALID_RESPONSE); 281 CompleteFetch(); 282 283 EXPECT_TRUE(callback_called_); 284 EXPECT_EQ(kAndroidId, android_id_); 285 EXPECT_EQ(kSecurityToken, security_token_); 286 } 287 288 TEST_F(CheckinRequestTest, ResponseMissingAndroidId) { 289 CreateRequest(0u, 0u); 290 request_->Start(); 291 292 SetResponse(MISSING_ANDROID_ID); 293 CompleteFetch(); 294 295 EXPECT_FALSE(callback_called_); 296 297 SetResponse(VALID_RESPONSE); 298 CompleteFetch(); 299 300 EXPECT_TRUE(callback_called_); 301 EXPECT_EQ(kAndroidId, android_id_); 302 EXPECT_EQ(kSecurityToken, security_token_); 303 } 304 305 TEST_F(CheckinRequestTest, ResponseMissingSecurityToken) { 306 CreateRequest(0u, 0u); 307 request_->Start(); 308 309 SetResponse(MISSING_SECURITY_TOKEN); 310 CompleteFetch(); 311 312 EXPECT_FALSE(callback_called_); 313 314 SetResponse(VALID_RESPONSE); 315 CompleteFetch(); 316 317 EXPECT_TRUE(callback_called_); 318 EXPECT_EQ(kAndroidId, android_id_); 319 EXPECT_EQ(kSecurityToken, security_token_); 320 } 321 322 TEST_F(CheckinRequestTest, AndroidIdEqualsZeroInResponse) { 323 CreateRequest(0u, 0u); 324 request_->Start(); 325 326 SetResponse(ANDROID_ID_IS_ZER0); 327 CompleteFetch(); 328 329 EXPECT_FALSE(callback_called_); 330 331 SetResponse(VALID_RESPONSE); 332 CompleteFetch(); 333 334 EXPECT_TRUE(callback_called_); 335 EXPECT_EQ(kAndroidId, android_id_); 336 EXPECT_EQ(kSecurityToken, security_token_); 337 } 338 339 TEST_F(CheckinRequestTest, SecurityTokenEqualsZeroInResponse) { 340 CreateRequest(0u, 0u); 341 request_->Start(); 342 343 SetResponse(SECURITY_TOKEN_IS_ZERO); 344 CompleteFetch(); 345 346 EXPECT_FALSE(callback_called_); 347 348 SetResponse(VALID_RESPONSE); 349 CompleteFetch(); 350 351 EXPECT_TRUE(callback_called_); 352 EXPECT_EQ(kAndroidId, android_id_); 353 EXPECT_EQ(kSecurityToken, security_token_); 354 } 355 356 TEST_F(CheckinRequestTest, SuccessfulFirstTimeCheckin) { 357 CreateRequest(0u, 0u); 358 request_->Start(); 359 360 SetResponse(VALID_RESPONSE); 361 CompleteFetch(); 362 363 EXPECT_TRUE(callback_called_); 364 EXPECT_EQ(kAndroidId, android_id_); 365 EXPECT_EQ(kSecurityToken, security_token_); 366 } 367 368 TEST_F(CheckinRequestTest, SuccessfulSubsequentCheckin) { 369 CreateRequest(kAndroidId, kSecurityToken); 370 request_->Start(); 371 372 SetResponse(VALID_RESPONSE); 373 CompleteFetch(); 374 375 EXPECT_TRUE(callback_called_); 376 EXPECT_EQ(kAndroidId, android_id_); 377 EXPECT_EQ(kSecurityToken, security_token_); 378 } 379 380 } // namespace gcm 381