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/unregistration_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_test_util.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace gcm {
     18 
     19 namespace {
     20 const uint64 kAndroidId = 42UL;
     21 const char kLoginHeader[] = "AidLogin";
     22 const char kAppId[] = "TestAppId";
     23 const char kDeletedAppId[] = "deleted=TestAppId";
     24 const char kRegistrationURL[] = "http://foo.bar/register";
     25 const uint64 kSecurityToken = 77UL;
     26 
     27 // Backoff policy for testing registration request.
     28 const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
     29   // Number of initial errors (in sequence) to ignore before applying
     30   // exponential back-off rules.
     31   // Explicitly set to 2 to skip the delay on the first retry, as we are not
     32   // trying to test the backoff itself, but rather the fact that retry happens.
     33   1,
     34 
     35   // Initial delay for exponential back-off in ms.
     36   15000,  // 15 seconds.
     37 
     38   // Factor by which the waiting time will be multiplied.
     39   2,
     40 
     41   // Fuzzing percentage. ex: 10% will spread requests randomly
     42   // between 90%-100% of the calculated time.
     43   0.5,  // 50%.
     44 
     45   // Maximum amount of time we are willing to delay our request in ms.
     46   1000 * 60 * 5, // 5 minutes.
     47 
     48   // Time to keep an entry from being discarded even when it
     49   // has no significant state, -1 to never discard.
     50   -1,
     51 
     52   // Don't use initial delay unless the last request was an error.
     53   false,
     54 };
     55 }  // namespace
     56 
     57 class UnregistrationRequestTest : public testing::Test {
     58  public:
     59   UnregistrationRequestTest();
     60   virtual ~UnregistrationRequestTest();
     61 
     62   void UnregistrationCallback(UnregistrationRequest::Status status);
     63 
     64   void CreateRequest();
     65   void SetResponseStatusAndString(net::HttpStatusCode status_code,
     66                                   const std::string& response_body);
     67   void CompleteFetch();
     68 
     69  protected:
     70   bool callback_called_;
     71   UnregistrationRequest::Status status_;
     72   scoped_ptr<UnregistrationRequest> request_;
     73   base::MessageLoop message_loop_;
     74   net::TestURLFetcherFactory url_fetcher_factory_;
     75   scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
     76   FakeGCMStatsRecorder recorder_;
     77 };
     78 
     79 UnregistrationRequestTest::UnregistrationRequestTest()
     80     : callback_called_(false),
     81       status_(UnregistrationRequest::UNREGISTRATION_STATUS_COUNT),
     82       url_request_context_getter_(new net::TestURLRequestContextGetter(
     83           message_loop_.message_loop_proxy())) {}
     84 
     85 UnregistrationRequestTest::~UnregistrationRequestTest() {}
     86 
     87 void UnregistrationRequestTest::UnregistrationCallback(
     88     UnregistrationRequest::Status status) {
     89   callback_called_ = true;
     90   status_ = status;
     91 }
     92 
     93 void UnregistrationRequestTest::CreateRequest() {
     94   request_.reset(new UnregistrationRequest(
     95       GURL(kRegistrationURL),
     96       UnregistrationRequest::RequestInfo(kAndroidId,
     97                                          kSecurityToken,
     98                                          kAppId),
     99       kDefaultBackoffPolicy,
    100       base::Bind(&UnregistrationRequestTest::UnregistrationCallback,
    101                  base::Unretained(this)),
    102       url_request_context_getter_.get(),
    103       &recorder_));
    104 }
    105 
    106 void UnregistrationRequestTest::SetResponseStatusAndString(
    107     net::HttpStatusCode status_code,
    108     const std::string& response_body) {
    109   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
    110   ASSERT_TRUE(fetcher);
    111   fetcher->set_response_code(status_code);
    112   fetcher->SetResponseString(response_body);
    113 }
    114 
    115 void UnregistrationRequestTest::CompleteFetch() {
    116   status_ = UnregistrationRequest::UNREGISTRATION_STATUS_COUNT;
    117   callback_called_ = false;
    118   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
    119   ASSERT_TRUE(fetcher);
    120   fetcher->delegate()->OnURLFetchComplete(fetcher);
    121 }
    122 
    123 TEST_F(UnregistrationRequestTest, RequestDataPassedToFetcher) {
    124   CreateRequest();
    125   request_->Start();
    126 
    127   // Get data sent by request.
    128   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
    129   ASSERT_TRUE(fetcher);
    130 
    131   EXPECT_EQ(GURL(kRegistrationURL), fetcher->GetOriginalURL());
    132 
    133   // Verify that authorization header was put together properly.
    134   net::HttpRequestHeaders headers;
    135   fetcher->GetExtraRequestHeaders(&headers);
    136   std::string auth_header;
    137   headers.GetHeader(net::HttpRequestHeaders::kAuthorization, &auth_header);
    138   base::StringTokenizer auth_tokenizer(auth_header, " :");
    139   ASSERT_TRUE(auth_tokenizer.GetNext());
    140   EXPECT_EQ(kLoginHeader, auth_tokenizer.token());
    141   ASSERT_TRUE(auth_tokenizer.GetNext());
    142   EXPECT_EQ(base::Uint64ToString(kAndroidId), auth_tokenizer.token());
    143   ASSERT_TRUE(auth_tokenizer.GetNext());
    144   EXPECT_EQ(base::Uint64ToString(kSecurityToken), auth_tokenizer.token());
    145   std::string app_id_header;
    146   headers.GetHeader("app", &app_id_header);
    147   EXPECT_EQ(kAppId, app_id_header);
    148 
    149   std::map<std::string, std::string> expected_pairs;
    150   expected_pairs["app"] = kAppId;
    151   expected_pairs["device"] = base::Uint64ToString(kAndroidId);
    152   expected_pairs["delete"] = "true";
    153   expected_pairs["gcm_unreg_caller"] = "false";
    154 
    155   // Verify data was formatted properly.
    156   std::string upload_data = fetcher->upload_data();
    157   base::StringTokenizer data_tokenizer(upload_data, "&=");
    158   while (data_tokenizer.GetNext()) {
    159     std::map<std::string, std::string>::iterator iter =
    160         expected_pairs.find(data_tokenizer.token());
    161     ASSERT_TRUE(iter != expected_pairs.end()) << data_tokenizer.token();
    162     ASSERT_TRUE(data_tokenizer.GetNext()) << data_tokenizer.token();
    163     EXPECT_EQ(iter->second, data_tokenizer.token());
    164     // Ensure that none of the keys appears twice.
    165     expected_pairs.erase(iter);
    166   }
    167 
    168   EXPECT_EQ(0UL, expected_pairs.size());
    169 }
    170 
    171 TEST_F(UnregistrationRequestTest, SuccessfulUnregistration) {
    172   CreateRequest();
    173   request_->Start();
    174 
    175   SetResponseStatusAndString(net::HTTP_OK, kDeletedAppId);
    176   CompleteFetch();
    177 
    178   EXPECT_TRUE(callback_called_);
    179   EXPECT_EQ(UnregistrationRequest::SUCCESS, status_);
    180 }
    181 
    182 TEST_F(UnregistrationRequestTest, ResponseHttpStatusNotOK) {
    183   CreateRequest();
    184   request_->Start();
    185 
    186   SetResponseStatusAndString(net::HTTP_UNAUTHORIZED, "");
    187   CompleteFetch();
    188 
    189   EXPECT_TRUE(callback_called_);
    190   EXPECT_EQ(UnregistrationRequest::HTTP_NOT_OK, status_);
    191 }
    192 
    193 TEST_F(UnregistrationRequestTest, ResponseEmpty) {
    194   CreateRequest();
    195   request_->Start();
    196 
    197   SetResponseStatusAndString(net::HTTP_OK, "");
    198   CompleteFetch();
    199 
    200   EXPECT_FALSE(callback_called_);
    201 
    202   SetResponseStatusAndString(net::HTTP_OK, kDeletedAppId);
    203   CompleteFetch();
    204 
    205   EXPECT_TRUE(callback_called_);
    206   EXPECT_EQ(UnregistrationRequest::SUCCESS, status_);
    207 }
    208 
    209 TEST_F(UnregistrationRequestTest, InvalidParametersError) {
    210   CreateRequest();
    211   request_->Start();
    212 
    213   SetResponseStatusAndString(net::HTTP_OK, "Error=INVALID_PARAMETERS");
    214   CompleteFetch();
    215 
    216   EXPECT_TRUE(callback_called_);
    217   EXPECT_EQ(UnregistrationRequest::INVALID_PARAMETERS, status_);
    218 }
    219 
    220 TEST_F(UnregistrationRequestTest, UnkwnownError) {
    221   CreateRequest();
    222   request_->Start();
    223 
    224   SetResponseStatusAndString(net::HTTP_OK, "Error=XXX");
    225   CompleteFetch();
    226 
    227   EXPECT_TRUE(callback_called_);
    228   EXPECT_EQ(UnregistrationRequest::UNKNOWN_ERROR, status_);
    229 }
    230 
    231 TEST_F(UnregistrationRequestTest, ServiceUnavailable) {
    232   CreateRequest();
    233   request_->Start();
    234 
    235   SetResponseStatusAndString(net::HTTP_SERVICE_UNAVAILABLE, "");
    236   CompleteFetch();
    237 
    238   EXPECT_FALSE(callback_called_);
    239 
    240   SetResponseStatusAndString(net::HTTP_OK, kDeletedAppId);
    241   CompleteFetch();
    242 
    243   EXPECT_TRUE(callback_called_);
    244   EXPECT_EQ(UnregistrationRequest::SUCCESS, status_);
    245 }
    246 
    247 TEST_F(UnregistrationRequestTest, InternalServerError) {
    248   CreateRequest();
    249   request_->Start();
    250 
    251   SetResponseStatusAndString(net::HTTP_INTERNAL_SERVER_ERROR, "");
    252   CompleteFetch();
    253 
    254   EXPECT_FALSE(callback_called_);
    255 
    256   SetResponseStatusAndString(net::HTTP_OK, kDeletedAppId);
    257   CompleteFetch();
    258 
    259   EXPECT_TRUE(callback_called_);
    260   EXPECT_EQ(UnregistrationRequest::SUCCESS, status_);
    261 }
    262 
    263 TEST_F(UnregistrationRequestTest, IncorrectAppId) {
    264   CreateRequest();
    265   request_->Start();
    266 
    267   SetResponseStatusAndString(net::HTTP_OK, "deleted=OtherTestAppId");
    268   CompleteFetch();
    269 
    270   EXPECT_FALSE(callback_called_);
    271 
    272   SetResponseStatusAndString(net::HTTP_OK, kDeletedAppId);
    273   CompleteFetch();
    274 
    275   EXPECT_TRUE(callback_called_);
    276   EXPECT_EQ(UnregistrationRequest::SUCCESS, status_);
    277 }
    278 
    279 TEST_F(UnregistrationRequestTest, ResponseParsingFailed) {
    280   CreateRequest();
    281   request_->Start();
    282 
    283   SetResponseStatusAndString(net::HTTP_OK, "some malformed response");
    284   CompleteFetch();
    285 
    286   EXPECT_FALSE(callback_called_);
    287 
    288   SetResponseStatusAndString(net::HTTP_OK, kDeletedAppId);
    289   CompleteFetch();
    290 
    291   EXPECT_TRUE(callback_called_);
    292   EXPECT_EQ(UnregistrationRequest::SUCCESS, status_);
    293 }
    294 
    295 }  // namespace gcm
    296