• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
UnregistrationRequestTest()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 
~UnregistrationRequestTest()85 UnregistrationRequestTest::~UnregistrationRequestTest() {}
86 
UnregistrationCallback(UnregistrationRequest::Status status)87 void UnregistrationRequestTest::UnregistrationCallback(
88     UnregistrationRequest::Status status) {
89   callback_called_ = true;
90   status_ = status;
91 }
92 
CreateRequest()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 
SetResponseStatusAndString(net::HttpStatusCode status_code,const std::string & response_body)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 
CompleteFetch()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 
TEST_F(UnregistrationRequestTest,RequestDataPassedToFetcher)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 
TEST_F(UnregistrationRequestTest,SuccessfulUnregistration)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 
TEST_F(UnregistrationRequestTest,ResponseHttpStatusNotOK)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 
TEST_F(UnregistrationRequestTest,ResponseEmpty)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 
TEST_F(UnregistrationRequestTest,InvalidParametersError)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 
TEST_F(UnregistrationRequestTest,UnkwnownError)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 
TEST_F(UnregistrationRequestTest,ServiceUnavailable)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 
TEST_F(UnregistrationRequestTest,InternalServerError)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 
TEST_F(UnregistrationRequestTest,IncorrectAppId)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 
TEST_F(UnregistrationRequestTest,ResponseParsingFailed)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