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 <map>
      6 #include <string>
      7 #include <vector>
      8 
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/strings/string_tokenizer.h"
     11 #include "google_apis/gcm/engine/registration_request.h"
     12 #include "google_apis/gcm/monitoring/fake_gcm_stats_recorder.h"
     13 #include "net/url_request/test_url_fetcher_factory.h"
     14 #include "net/url_request/url_request_status.h"
     15 #include "net/url_request/url_request_test_util.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace gcm {
     19 
     20 namespace {
     21 const uint64 kAndroidId = 42UL;
     22 const char kAppId[] = "TestAppId";
     23 const char kDeveloperId[] = "Project1";
     24 const char kLoginHeader[] = "AidLogin";
     25 const char kRegistrationURL[] = "http://foo.bar/register";
     26 const uint64 kSecurityToken = 77UL;
     27 
     28 // Backoff policy for testing registration request.
     29 const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
     30   // Number of initial errors (in sequence) to ignore before applying
     31   // exponential back-off rules.
     32   // Explicitly set to 2 to skip the delay on the first retry, as we are not
     33   // trying to test the backoff itself, but rather the fact that retry happens.
     34   2,
     35 
     36   // Initial delay for exponential back-off in ms.
     37   15000,  // 15 seconds.
     38 
     39   // Factor by which the waiting time will be multiplied.
     40   2,
     41 
     42   // Fuzzing percentage. ex: 10% will spread requests randomly
     43   // between 90%-100% of the calculated time.
     44   0.5,  // 50%.
     45 
     46   // Maximum amount of time we are willing to delay our request in ms.
     47   1000 * 60 * 5, // 5 minutes.
     48 
     49   // Time to keep an entry from being discarded even when it
     50   // has no significant state, -1 to never discard.
     51   -1,
     52 
     53   // Don't use initial delay unless the last request was an error.
     54   false,
     55 };
     56 
     57 }  // namespace
     58 
     59 class RegistrationRequestTest : public testing::Test {
     60  public:
     61   RegistrationRequestTest();
     62   virtual ~RegistrationRequestTest();
     63 
     64   void RegistrationCallback(RegistrationRequest::Status status,
     65                             const std::string& registration_id);
     66 
     67   void CreateRequest(const std::string& sender_ids);
     68   void SetResponseStatusAndString(net::HttpStatusCode status_code,
     69                                   const std::string& response_body);
     70   void CompleteFetch();
     71   void set_max_retry_count(int max_retry_count) {
     72     max_retry_count_ = max_retry_count;
     73   }
     74 
     75  protected:
     76   int max_retry_count_;
     77   RegistrationRequest::Status status_;
     78   std::string registration_id_;
     79   bool callback_called_;
     80   std::map<std::string, std::string> extras_;
     81   scoped_ptr<RegistrationRequest> request_;
     82   base::MessageLoop message_loop_;
     83   net::TestURLFetcherFactory url_fetcher_factory_;
     84   scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
     85   FakeGCMStatsRecorder recorder_;
     86 };
     87 
     88 RegistrationRequestTest::RegistrationRequestTest()
     89     : max_retry_count_(2),
     90       status_(RegistrationRequest::SUCCESS),
     91       callback_called_(false),
     92       url_request_context_getter_(new net::TestURLRequestContextGetter(
     93           message_loop_.message_loop_proxy())) {}
     94 
     95 RegistrationRequestTest::~RegistrationRequestTest() {}
     96 
     97 void RegistrationRequestTest::RegistrationCallback(
     98     RegistrationRequest::Status status,
     99     const std::string& registration_id) {
    100   status_ = status;
    101   registration_id_ = registration_id;
    102   callback_called_ = true;
    103 }
    104 
    105 void RegistrationRequestTest::CreateRequest(const std::string& sender_ids) {
    106   std::vector<std::string> senders;
    107   base::StringTokenizer tokenizer(sender_ids, ",");
    108   while (tokenizer.GetNext())
    109     senders.push_back(tokenizer.token());
    110 
    111   request_.reset(new RegistrationRequest(
    112       GURL(kRegistrationURL),
    113       RegistrationRequest::RequestInfo(kAndroidId,
    114                                        kSecurityToken,
    115                                        kAppId,
    116                                        senders),
    117       kDefaultBackoffPolicy,
    118       base::Bind(&RegistrationRequestTest::RegistrationCallback,
    119                  base::Unretained(this)),
    120       max_retry_count_,
    121       url_request_context_getter_.get(),
    122       &recorder_));
    123 }
    124 
    125 void RegistrationRequestTest::SetResponseStatusAndString(
    126     net::HttpStatusCode status_code,
    127     const std::string& response_body) {
    128   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
    129   ASSERT_TRUE(fetcher);
    130   fetcher->set_response_code(status_code);
    131   fetcher->SetResponseString(response_body);
    132 }
    133 
    134 void RegistrationRequestTest::CompleteFetch() {
    135   registration_id_.clear();
    136   status_ = RegistrationRequest::SUCCESS;
    137   callback_called_ = false;
    138 
    139   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
    140   ASSERT_TRUE(fetcher);
    141   fetcher->delegate()->OnURLFetchComplete(fetcher);
    142 }
    143 
    144 TEST_F(RegistrationRequestTest, RequestSuccessful) {
    145   set_max_retry_count(0);
    146   CreateRequest("sender1,sender2");
    147   request_->Start();
    148 
    149   SetResponseStatusAndString(net::HTTP_OK, "token=2501");
    150   CompleteFetch();
    151 
    152   EXPECT_TRUE(callback_called_);
    153   EXPECT_EQ(RegistrationRequest::SUCCESS, status_);
    154   EXPECT_EQ("2501", registration_id_);
    155 }
    156 
    157 TEST_F(RegistrationRequestTest, RequestDataAndURL) {
    158   CreateRequest(kDeveloperId);
    159   request_->Start();
    160 
    161   // Get data sent by request.
    162   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
    163   ASSERT_TRUE(fetcher);
    164 
    165   EXPECT_EQ(GURL(kRegistrationURL), fetcher->GetOriginalURL());
    166 
    167   // Verify that authorization header was put together properly.
    168   net::HttpRequestHeaders headers;
    169   fetcher->GetExtraRequestHeaders(&headers);
    170   std::string auth_header;
    171   headers.GetHeader(net::HttpRequestHeaders::kAuthorization, &auth_header);
    172   base::StringTokenizer auth_tokenizer(auth_header, " :");
    173   ASSERT_TRUE(auth_tokenizer.GetNext());
    174   EXPECT_EQ(kLoginHeader, auth_tokenizer.token());
    175   ASSERT_TRUE(auth_tokenizer.GetNext());
    176   EXPECT_EQ(base::Uint64ToString(kAndroidId), auth_tokenizer.token());
    177   ASSERT_TRUE(auth_tokenizer.GetNext());
    178   EXPECT_EQ(base::Uint64ToString(kSecurityToken), auth_tokenizer.token());
    179 
    180   std::map<std::string, std::string> expected_pairs;
    181   expected_pairs["app"] = kAppId;
    182   expected_pairs["sender"] = kDeveloperId;
    183   expected_pairs["device"] = base::Uint64ToString(kAndroidId);
    184 
    185   // Verify data was formatted properly.
    186   std::string upload_data = fetcher->upload_data();
    187   base::StringTokenizer data_tokenizer(upload_data, "&=");
    188   while (data_tokenizer.GetNext()) {
    189     std::map<std::string, std::string>::iterator iter =
    190         expected_pairs.find(data_tokenizer.token());
    191     ASSERT_TRUE(iter != expected_pairs.end());
    192     ASSERT_TRUE(data_tokenizer.GetNext());
    193     EXPECT_EQ(iter->second, data_tokenizer.token());
    194     // Ensure that none of the keys appears twice.
    195     expected_pairs.erase(iter);
    196   }
    197 
    198   EXPECT_EQ(0UL, expected_pairs.size());
    199 }
    200 
    201 TEST_F(RegistrationRequestTest, RequestRegistrationWithMultipleSenderIds) {
    202   CreateRequest("sender1,sender2 (at) gmail.com");
    203   request_->Start();
    204 
    205   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
    206   ASSERT_TRUE(fetcher);
    207 
    208   // Verify data was formatted properly.
    209   std::string upload_data = fetcher->upload_data();
    210   base::StringTokenizer data_tokenizer(upload_data, "&=");
    211 
    212   // Skip all tokens until you hit entry for senders.
    213   while (data_tokenizer.GetNext() && data_tokenizer.token() != "sender")
    214     continue;
    215 
    216   ASSERT_TRUE(data_tokenizer.GetNext());
    217   std::string senders(net::UnescapeURLComponent(data_tokenizer.token(),
    218       net::UnescapeRule::URL_SPECIAL_CHARS));
    219   base::StringTokenizer sender_tokenizer(senders, ",");
    220   ASSERT_TRUE(sender_tokenizer.GetNext());
    221   EXPECT_EQ("sender1", sender_tokenizer.token());
    222   ASSERT_TRUE(sender_tokenizer.GetNext());
    223   EXPECT_EQ("sender2 (at) gmail.com", sender_tokenizer.token());
    224 }
    225 
    226 TEST_F(RegistrationRequestTest, ResponseParsing) {
    227   CreateRequest("sender1,sender2");
    228   request_->Start();
    229 
    230   SetResponseStatusAndString(net::HTTP_OK, "token=2501");
    231   CompleteFetch();
    232 
    233   EXPECT_TRUE(callback_called_);
    234   EXPECT_EQ(RegistrationRequest::SUCCESS, status_);
    235   EXPECT_EQ("2501", registration_id_);
    236 }
    237 
    238 TEST_F(RegistrationRequestTest, ResponseHttpStatusNotOK) {
    239   CreateRequest("sender1,sender2");
    240   request_->Start();
    241 
    242   SetResponseStatusAndString(net::HTTP_UNAUTHORIZED, "token=2501");
    243   CompleteFetch();
    244 
    245   EXPECT_FALSE(callback_called_);
    246 
    247   SetResponseStatusAndString(net::HTTP_OK, "token=2501");
    248   CompleteFetch();
    249 
    250   EXPECT_TRUE(callback_called_);
    251   EXPECT_EQ(RegistrationRequest::SUCCESS, status_);
    252   EXPECT_EQ("2501", registration_id_);
    253 }
    254 
    255 TEST_F(RegistrationRequestTest, ResponseMissingRegistrationId) {
    256   CreateRequest("sender1,sender2");
    257   request_->Start();
    258 
    259   SetResponseStatusAndString(net::HTTP_OK, "");
    260   CompleteFetch();
    261 
    262   EXPECT_FALSE(callback_called_);
    263 
    264   SetResponseStatusAndString(net::HTTP_OK, "some error in response");
    265   CompleteFetch();
    266 
    267   EXPECT_FALSE(callback_called_);
    268 
    269   // Ensuring a retry happened and succeeds.
    270   SetResponseStatusAndString(net::HTTP_OK, "token=2501");
    271   CompleteFetch();
    272 
    273   EXPECT_TRUE(callback_called_);
    274   EXPECT_EQ(RegistrationRequest::SUCCESS, status_);
    275   EXPECT_EQ("2501", registration_id_);
    276 }
    277 
    278 TEST_F(RegistrationRequestTest, ResponseDeviceRegistrationError) {
    279   CreateRequest("sender1,sender2");
    280   request_->Start();
    281 
    282   SetResponseStatusAndString(net::HTTP_OK, "Error=PHONE_REGISTRATION_ERROR");
    283   CompleteFetch();
    284 
    285   EXPECT_FALSE(callback_called_);
    286 
    287   // Ensuring a retry happened and succeeds.
    288   SetResponseStatusAndString(net::HTTP_OK, "token=2501");
    289   CompleteFetch();
    290 
    291   EXPECT_TRUE(callback_called_);
    292   EXPECT_EQ(RegistrationRequest::SUCCESS, status_);
    293   EXPECT_EQ("2501", registration_id_);
    294 }
    295 
    296 TEST_F(RegistrationRequestTest, ResponseAuthenticationError) {
    297   CreateRequest("sender1,sender2");
    298   request_->Start();
    299 
    300   SetResponseStatusAndString(net::HTTP_UNAUTHORIZED,
    301                              "Error=AUTHENTICATION_FAILED");
    302   CompleteFetch();
    303 
    304   EXPECT_FALSE(callback_called_);
    305 
    306   // Ensuring a retry happened and succeeds.
    307   SetResponseStatusAndString(net::HTTP_OK, "token=2501");
    308   CompleteFetch();
    309 
    310   EXPECT_TRUE(callback_called_);
    311   EXPECT_EQ(RegistrationRequest::SUCCESS, status_);
    312   EXPECT_EQ("2501", registration_id_);
    313 }
    314 
    315 TEST_F(RegistrationRequestTest, ResponseInvalidParameters) {
    316   CreateRequest("sender1,sender2");
    317   request_->Start();
    318 
    319   SetResponseStatusAndString(net::HTTP_OK, "Error=INVALID_PARAMETERS");
    320   CompleteFetch();
    321 
    322   EXPECT_TRUE(callback_called_);
    323   EXPECT_EQ(RegistrationRequest::INVALID_PARAMETERS, status_);
    324   EXPECT_EQ(std::string(), registration_id_);
    325 }
    326 
    327 TEST_F(RegistrationRequestTest, ResponseInvalidSender) {
    328   CreateRequest("sender1,sender2");
    329   request_->Start();
    330 
    331   SetResponseStatusAndString(net::HTTP_OK, "Error=INVALID_SENDER");
    332   CompleteFetch();
    333 
    334   EXPECT_TRUE(callback_called_);
    335   EXPECT_EQ(RegistrationRequest::INVALID_SENDER, status_);
    336   EXPECT_EQ(std::string(), registration_id_);
    337 }
    338 
    339 TEST_F(RegistrationRequestTest, ResponseInvalidSenderBadRequest) {
    340   CreateRequest("sender1");
    341   request_->Start();
    342 
    343   SetResponseStatusAndString(net::HTTP_BAD_REQUEST, "Error=INVALID_SENDER");
    344   CompleteFetch();
    345 
    346   EXPECT_TRUE(callback_called_);
    347   EXPECT_EQ(RegistrationRequest::INVALID_SENDER, status_);
    348   EXPECT_EQ(std::string(), registration_id_);
    349 }
    350 
    351 TEST_F(RegistrationRequestTest, RequestNotSuccessful) {
    352   CreateRequest("sender1,sender2");
    353   request_->Start();
    354 
    355   net::URLRequestStatus request_status(net::URLRequestStatus::FAILED, 1);
    356   SetResponseStatusAndString(net::HTTP_OK, "token=2501");
    357   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
    358   ASSERT_TRUE(fetcher);
    359   fetcher->set_status(request_status);
    360 
    361   CompleteFetch();
    362 
    363   EXPECT_FALSE(callback_called_);
    364 
    365   // Ensuring a retry happened and succeeded.
    366   SetResponseStatusAndString(net::HTTP_OK, "token=2501");
    367   CompleteFetch();
    368 
    369   EXPECT_TRUE(callback_called_);
    370   EXPECT_EQ(RegistrationRequest::SUCCESS, status_);
    371   EXPECT_EQ("2501", registration_id_);
    372 }
    373 
    374 TEST_F(RegistrationRequestTest, ResponseHttpNotOk) {
    375   CreateRequest("sender1,sender2");
    376   request_->Start();
    377 
    378   SetResponseStatusAndString(net::HTTP_GATEWAY_TIMEOUT, "token=2501");
    379   CompleteFetch();
    380 
    381   EXPECT_FALSE(callback_called_);
    382 
    383   // Ensuring a retry happened and succeeded.
    384   SetResponseStatusAndString(net::HTTP_OK, "token=2501");
    385   CompleteFetch();
    386 
    387   EXPECT_TRUE(callback_called_);
    388   EXPECT_EQ(RegistrationRequest::SUCCESS, status_);
    389   EXPECT_EQ("2501", registration_id_);
    390 }
    391 
    392 TEST_F(RegistrationRequestTest, MaximumAttemptsReachedWithZeroRetries) {
    393   set_max_retry_count(0);
    394   CreateRequest("sender1,sender2");
    395   request_->Start();
    396 
    397   SetResponseStatusAndString(net::HTTP_GATEWAY_TIMEOUT, "token=2501");
    398   CompleteFetch();
    399 
    400   EXPECT_TRUE(callback_called_);
    401   EXPECT_EQ(RegistrationRequest::REACHED_MAX_RETRIES, status_);
    402   EXPECT_EQ(std::string(), registration_id_);
    403 }
    404 
    405 TEST_F(RegistrationRequestTest, MaximumAttemptsReached) {
    406   CreateRequest("sender1,sender2");
    407   request_->Start();
    408 
    409   SetResponseStatusAndString(net::HTTP_GATEWAY_TIMEOUT, "token=2501");
    410   CompleteFetch();
    411 
    412   EXPECT_FALSE(callback_called_);
    413 
    414   SetResponseStatusAndString(net::HTTP_GATEWAY_TIMEOUT, "token=2501");
    415   CompleteFetch();
    416 
    417   EXPECT_FALSE(callback_called_);
    418 
    419   SetResponseStatusAndString(net::HTTP_GATEWAY_TIMEOUT, "token=2501");
    420   CompleteFetch();
    421 
    422   EXPECT_TRUE(callback_called_);
    423   EXPECT_EQ(RegistrationRequest::REACHED_MAX_RETRIES, status_);
    424   EXPECT_EQ(std::string(), registration_id_);
    425 }
    426 
    427 }  // namespace gcm
    428