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
18namespace gcm {
19
20namespace {
21const uint64 kAndroidId = 42UL;
22const char kAppId[] = "TestAppId";
23const char kDeveloperId[] = "Project1";
24const char kLoginHeader[] = "AidLogin";
25const char kRegistrationURL[] = "http://foo.bar/register";
26const uint64 kSecurityToken = 77UL;
27
28// Backoff policy for testing registration request.
29const 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
59class 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
88RegistrationRequestTest::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
95RegistrationRequestTest::~RegistrationRequestTest() {}
96
97void 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
105void 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
125void 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
134void 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
144TEST_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
157TEST_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
201TEST_F(RegistrationRequestTest, RequestRegistrationWithMultipleSenderIds) {
202  CreateRequest("sender1,sender2@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@gmail.com", sender_tokenizer.token());
224}
225
226TEST_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
238TEST_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
255TEST_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
278TEST_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
296TEST_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
315TEST_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
327TEST_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
339TEST_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
351TEST_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
374TEST_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
392TEST_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
405TEST_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