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 
     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