Home | History | Annotate | Download | only in engine
      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 const char kEmailAddress[] = "test_user (at) gmail.com";
     57 const char kTokenValue[] = "token_value";
     58 
     59 class CheckinRequestTest : public testing::Test {
     60  public:
     61   enum ResponseScenario {
     62     VALID_RESPONSE,  // Both android_id and security_token set in response.
     63     MISSING_ANDROID_ID,  // android_id is missing.
     64     MISSING_SECURITY_TOKEN,  // security_token is missing.
     65     ANDROID_ID_IS_ZER0,  // android_id is 0.
     66     SECURITY_TOKEN_IS_ZERO  // security_token is 0.
     67   };
     68 
     69   CheckinRequestTest();
     70   virtual ~CheckinRequestTest();
     71 
     72   void FetcherCallback(
     73       const checkin_proto::AndroidCheckinResponse& response);
     74 
     75   void CreateRequest(uint64 android_id, uint64 security_token);
     76 
     77   void SetResponseStatusAndString(
     78       net::HttpStatusCode status_code,
     79       const std::string& response_data);
     80 
     81   void CompleteFetch();
     82 
     83   void SetResponse(ResponseScenario response_scenario);
     84 
     85  protected:
     86   bool callback_called_;
     87   uint64 android_id_;
     88   uint64 security_token_;
     89   int checkin_device_type_;
     90   base::MessageLoop message_loop_;
     91   net::TestURLFetcherFactory url_fetcher_factory_;
     92   scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
     93   checkin_proto::ChromeBuildProto chrome_build_proto_;
     94   scoped_ptr<CheckinRequest> request_;
     95   FakeGCMStatsRecorder recorder_;
     96 };
     97 
     98 CheckinRequestTest::CheckinRequestTest()
     99     : callback_called_(false),
    100       android_id_(kBlankAndroidId),
    101       security_token_(kBlankSecurityToken),
    102       checkin_device_type_(0),
    103       url_request_context_getter_(new net::TestURLRequestContextGetter(
    104           message_loop_.message_loop_proxy())) {
    105 }
    106 
    107 CheckinRequestTest::~CheckinRequestTest() {}
    108 
    109 void CheckinRequestTest::FetcherCallback(
    110     const checkin_proto::AndroidCheckinResponse& checkin_response) {
    111   callback_called_ = true;
    112   if (checkin_response.has_android_id())
    113     android_id_ = checkin_response.android_id();
    114   if (checkin_response.has_security_token())
    115     security_token_ = checkin_response.security_token();
    116 }
    117 
    118 void CheckinRequestTest::CreateRequest(uint64 android_id,
    119                                        uint64 security_token) {
    120   // First setup a chrome_build protobuf.
    121   chrome_build_proto_.set_platform(
    122       checkin_proto::ChromeBuildProto::PLATFORM_LINUX);
    123   chrome_build_proto_.set_channel(
    124       checkin_proto::ChromeBuildProto::CHANNEL_CANARY);
    125   chrome_build_proto_.set_chrome_version(kChromeVersion);
    126 
    127   std::map<std::string, std::string> account_tokens;
    128   account_tokens[kEmailAddress] = kTokenValue;
    129 
    130   CheckinRequest::RequestInfo request_info(android_id,
    131                                            security_token,
    132                                            account_tokens,
    133                                            kSettingsDigest,
    134                                            chrome_build_proto_);
    135   // Then create a request with that protobuf and specified android_id,
    136   // security_token.
    137   request_.reset(new CheckinRequest(
    138       GURL(kCheckinURL),
    139       request_info,
    140       kDefaultBackoffPolicy,
    141       base::Bind(&CheckinRequestTest::FetcherCallback, base::Unretained(this)),
    142       url_request_context_getter_.get(),
    143       &recorder_));
    144 
    145   // Setting android_id_ and security_token_ to blank value, not used elsewhere
    146   // in the tests.
    147   callback_called_ = false;
    148   android_id_ = kBlankAndroidId;
    149   security_token_ = kBlankSecurityToken;
    150 }
    151 
    152 void CheckinRequestTest::SetResponseStatusAndString(
    153     net::HttpStatusCode status_code,
    154     const std::string& response_data) {
    155   net::TestURLFetcher* fetcher =
    156       url_fetcher_factory_.GetFetcherByID(0);
    157   ASSERT_TRUE(fetcher);
    158   fetcher->set_response_code(status_code);
    159   fetcher->SetResponseString(response_data);
    160 }
    161 
    162 void CheckinRequestTest::CompleteFetch() {
    163   net::TestURLFetcher* fetcher =
    164       url_fetcher_factory_.GetFetcherByID(0);
    165   ASSERT_TRUE(fetcher);
    166   fetcher->delegate()->OnURLFetchComplete(fetcher);
    167 }
    168 
    169 void CheckinRequestTest::SetResponse(ResponseScenario response_scenario) {
    170   checkin_proto::AndroidCheckinResponse response;
    171   response.set_stats_ok(true);
    172 
    173   uint64 android_id = response_scenario == ANDROID_ID_IS_ZER0 ? 0 : kAndroidId;
    174   uint64 security_token =
    175       response_scenario == SECURITY_TOKEN_IS_ZERO ? 0 : kSecurityToken;
    176 
    177   if (response_scenario != MISSING_ANDROID_ID)
    178     response.set_android_id(android_id);
    179 
    180   if (response_scenario != MISSING_SECURITY_TOKEN)
    181     response.set_security_token(security_token);
    182 
    183   std::string response_string;
    184   response.SerializeToString(&response_string);
    185   SetResponseStatusAndString(net::HTTP_OK, response_string);
    186 }
    187 
    188 TEST_F(CheckinRequestTest, FetcherDataAndURL) {
    189   CreateRequest(kAndroidId, kSecurityToken);
    190   request_->Start();
    191 
    192   // Get data sent by request.
    193   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
    194   ASSERT_TRUE(fetcher);
    195   EXPECT_EQ(GURL(kCheckinURL), fetcher->GetOriginalURL());
    196 
    197   checkin_proto::AndroidCheckinRequest request_proto;
    198   request_proto.ParseFromString(fetcher->upload_data());
    199   EXPECT_EQ(kAndroidId, static_cast<uint64>(request_proto.id()));
    200   EXPECT_EQ(kSecurityToken, request_proto.security_token());
    201   EXPECT_EQ(chrome_build_proto_.platform(),
    202             request_proto.checkin().chrome_build().platform());
    203   EXPECT_EQ(chrome_build_proto_.chrome_version(),
    204             request_proto.checkin().chrome_build().chrome_version());
    205   EXPECT_EQ(chrome_build_proto_.channel(),
    206             request_proto.checkin().chrome_build().channel());
    207   EXPECT_EQ(2, request_proto.account_cookie_size());
    208   EXPECT_EQ(kEmailAddress, request_proto.account_cookie(0));
    209   EXPECT_EQ(kTokenValue, request_proto.account_cookie(1));
    210 
    211 #if defined(CHROME_OS)
    212   EXPECT_EQ(checkin_proto::DEVICE_CHROME_OS, request_proto.checkin().type());
    213 #else
    214   EXPECT_EQ(checkin_proto::DEVICE_CHROME_BROWSER,
    215             request_proto.checkin().type());
    216 #endif
    217 
    218   EXPECT_EQ(kSettingsDigest, request_proto.digest());
    219 }
    220 
    221 TEST_F(CheckinRequestTest, ResponseBodyEmpty) {
    222   CreateRequest(0u, 0u);
    223   request_->Start();
    224 
    225   SetResponseStatusAndString(net::HTTP_OK, std::string());
    226   CompleteFetch();
    227 
    228   EXPECT_FALSE(callback_called_);
    229 
    230   SetResponse(VALID_RESPONSE);
    231   CompleteFetch();
    232 
    233   EXPECT_TRUE(callback_called_);
    234   EXPECT_EQ(kAndroidId, android_id_);
    235   EXPECT_EQ(kSecurityToken, security_token_);
    236 }
    237 
    238 TEST_F(CheckinRequestTest, ResponseBodyCorrupted) {
    239   CreateRequest(0u, 0u);
    240   request_->Start();
    241 
    242   SetResponseStatusAndString(net::HTTP_OK, "Corrupted response body");
    243   CompleteFetch();
    244 
    245   EXPECT_FALSE(callback_called_);
    246 
    247   SetResponse(VALID_RESPONSE);
    248   CompleteFetch();
    249 
    250   EXPECT_TRUE(callback_called_);
    251   EXPECT_EQ(kAndroidId, android_id_);
    252   EXPECT_EQ(kSecurityToken, security_token_);
    253 }
    254 
    255 TEST_F(CheckinRequestTest, ResponseHttpStatusUnauthorized) {
    256   CreateRequest(0u, 0u);
    257   request_->Start();
    258 
    259   SetResponseStatusAndString(net::HTTP_UNAUTHORIZED, std::string());
    260   CompleteFetch();
    261 
    262   EXPECT_TRUE(callback_called_);
    263   EXPECT_EQ(kBlankAndroidId, android_id_);
    264   EXPECT_EQ(kBlankSecurityToken, security_token_);
    265 }
    266 
    267 TEST_F(CheckinRequestTest, ResponseHttpStatusBadRequest) {
    268   CreateRequest(0u, 0u);
    269   request_->Start();
    270 
    271   SetResponseStatusAndString(net::HTTP_BAD_REQUEST, std::string());
    272   CompleteFetch();
    273 
    274   EXPECT_TRUE(callback_called_);
    275   EXPECT_EQ(kBlankAndroidId, android_id_);
    276   EXPECT_EQ(kBlankSecurityToken, security_token_);
    277 }
    278 
    279 TEST_F(CheckinRequestTest, ResponseHttpStatusNotOK) {
    280   CreateRequest(0u, 0u);
    281   request_->Start();
    282 
    283   SetResponseStatusAndString(net::HTTP_INTERNAL_SERVER_ERROR, std::string());
    284   CompleteFetch();
    285 
    286   EXPECT_FALSE(callback_called_);
    287 
    288   SetResponse(VALID_RESPONSE);
    289   CompleteFetch();
    290 
    291   EXPECT_TRUE(callback_called_);
    292   EXPECT_EQ(kAndroidId, android_id_);
    293   EXPECT_EQ(kSecurityToken, security_token_);
    294 }
    295 
    296 TEST_F(CheckinRequestTest, ResponseMissingAndroidId) {
    297   CreateRequest(0u, 0u);
    298   request_->Start();
    299 
    300   SetResponse(MISSING_ANDROID_ID);
    301   CompleteFetch();
    302 
    303   EXPECT_FALSE(callback_called_);
    304 
    305   SetResponse(VALID_RESPONSE);
    306   CompleteFetch();
    307 
    308   EXPECT_TRUE(callback_called_);
    309   EXPECT_EQ(kAndroidId, android_id_);
    310   EXPECT_EQ(kSecurityToken, security_token_);
    311 }
    312 
    313 TEST_F(CheckinRequestTest, ResponseMissingSecurityToken) {
    314   CreateRequest(0u, 0u);
    315   request_->Start();
    316 
    317   SetResponse(MISSING_SECURITY_TOKEN);
    318   CompleteFetch();
    319 
    320   EXPECT_FALSE(callback_called_);
    321 
    322   SetResponse(VALID_RESPONSE);
    323   CompleteFetch();
    324 
    325   EXPECT_TRUE(callback_called_);
    326   EXPECT_EQ(kAndroidId, android_id_);
    327   EXPECT_EQ(kSecurityToken, security_token_);
    328 }
    329 
    330 TEST_F(CheckinRequestTest, AndroidIdEqualsZeroInResponse) {
    331   CreateRequest(0u, 0u);
    332   request_->Start();
    333 
    334   SetResponse(ANDROID_ID_IS_ZER0);
    335   CompleteFetch();
    336 
    337   EXPECT_FALSE(callback_called_);
    338 
    339   SetResponse(VALID_RESPONSE);
    340   CompleteFetch();
    341 
    342   EXPECT_TRUE(callback_called_);
    343   EXPECT_EQ(kAndroidId, android_id_);
    344   EXPECT_EQ(kSecurityToken, security_token_);
    345 }
    346 
    347 TEST_F(CheckinRequestTest, SecurityTokenEqualsZeroInResponse) {
    348   CreateRequest(0u, 0u);
    349   request_->Start();
    350 
    351   SetResponse(SECURITY_TOKEN_IS_ZERO);
    352   CompleteFetch();
    353 
    354   EXPECT_FALSE(callback_called_);
    355 
    356   SetResponse(VALID_RESPONSE);
    357   CompleteFetch();
    358 
    359   EXPECT_TRUE(callback_called_);
    360   EXPECT_EQ(kAndroidId, android_id_);
    361   EXPECT_EQ(kSecurityToken, security_token_);
    362 }
    363 
    364 TEST_F(CheckinRequestTest, SuccessfulFirstTimeCheckin) {
    365   CreateRequest(0u, 0u);
    366   request_->Start();
    367 
    368   SetResponse(VALID_RESPONSE);
    369   CompleteFetch();
    370 
    371   EXPECT_TRUE(callback_called_);
    372   EXPECT_EQ(kAndroidId, android_id_);
    373   EXPECT_EQ(kSecurityToken, security_token_);
    374 }
    375 
    376 TEST_F(CheckinRequestTest, SuccessfulSubsequentCheckin) {
    377   CreateRequest(kAndroidId, kSecurityToken);
    378   request_->Start();
    379 
    380   SetResponse(VALID_RESPONSE);
    381   CompleteFetch();
    382 
    383   EXPECT_TRUE(callback_called_);
    384   EXPECT_EQ(kAndroidId, android_id_);
    385   EXPECT_EQ(kSecurityToken, security_token_);
    386 }
    387 
    388 }  // namespace gcm
    389