• 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 <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 const char kEmailAddress[] = "test_user@gmail.com";
57 const char kTokenValue[] = "token_value";
58 
59 class CheckinRequestTest : public testing::Test {
60  public:
61   enum ResponseScenario {
62     VALID_RESPONSE,  // Both android_id and security_token set in response.
63     MISSING_ANDROID_ID,  // android_id is missing.
64     MISSING_SECURITY_TOKEN,  // security_token is missing.
65     ANDROID_ID_IS_ZER0,  // android_id is 0.
66     SECURITY_TOKEN_IS_ZERO  // security_token is 0.
67   };
68 
69   CheckinRequestTest();
70   virtual ~CheckinRequestTest();
71 
72   void FetcherCallback(
73       const checkin_proto::AndroidCheckinResponse& response);
74 
75   void CreateRequest(uint64 android_id, uint64 security_token);
76 
77   void SetResponseStatusAndString(
78       net::HttpStatusCode status_code,
79       const std::string& response_data);
80 
81   void CompleteFetch();
82 
83   void SetResponse(ResponseScenario response_scenario);
84 
85  protected:
86   bool callback_called_;
87   uint64 android_id_;
88   uint64 security_token_;
89   int checkin_device_type_;
90   base::MessageLoop message_loop_;
91   net::TestURLFetcherFactory url_fetcher_factory_;
92   scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
93   checkin_proto::ChromeBuildProto chrome_build_proto_;
94   scoped_ptr<CheckinRequest> request_;
95   FakeGCMStatsRecorder recorder_;
96 };
97 
CheckinRequestTest()98 CheckinRequestTest::CheckinRequestTest()
99     : callback_called_(false),
100       android_id_(kBlankAndroidId),
101       security_token_(kBlankSecurityToken),
102       checkin_device_type_(0),
103       url_request_context_getter_(new net::TestURLRequestContextGetter(
104           message_loop_.message_loop_proxy())) {
105 }
106 
~CheckinRequestTest()107 CheckinRequestTest::~CheckinRequestTest() {}
108 
FetcherCallback(const checkin_proto::AndroidCheckinResponse & checkin_response)109 void CheckinRequestTest::FetcherCallback(
110     const checkin_proto::AndroidCheckinResponse& checkin_response) {
111   callback_called_ = true;
112   if (checkin_response.has_android_id())
113     android_id_ = checkin_response.android_id();
114   if (checkin_response.has_security_token())
115     security_token_ = checkin_response.security_token();
116 }
117 
CreateRequest(uint64 android_id,uint64 security_token)118 void CheckinRequestTest::CreateRequest(uint64 android_id,
119                                        uint64 security_token) {
120   // First setup a chrome_build protobuf.
121   chrome_build_proto_.set_platform(
122       checkin_proto::ChromeBuildProto::PLATFORM_LINUX);
123   chrome_build_proto_.set_channel(
124       checkin_proto::ChromeBuildProto::CHANNEL_CANARY);
125   chrome_build_proto_.set_chrome_version(kChromeVersion);
126 
127   std::map<std::string, std::string> account_tokens;
128   account_tokens[kEmailAddress] = kTokenValue;
129 
130   CheckinRequest::RequestInfo request_info(android_id,
131                                            security_token,
132                                            account_tokens,
133                                            kSettingsDigest,
134                                            chrome_build_proto_);
135   // Then create a request with that protobuf and specified android_id,
136   // security_token.
137   request_.reset(new CheckinRequest(
138       GURL(kCheckinURL),
139       request_info,
140       kDefaultBackoffPolicy,
141       base::Bind(&CheckinRequestTest::FetcherCallback, base::Unretained(this)),
142       url_request_context_getter_.get(),
143       &recorder_));
144 
145   // Setting android_id_ and security_token_ to blank value, not used elsewhere
146   // in the tests.
147   callback_called_ = false;
148   android_id_ = kBlankAndroidId;
149   security_token_ = kBlankSecurityToken;
150 }
151 
SetResponseStatusAndString(net::HttpStatusCode status_code,const std::string & response_data)152 void CheckinRequestTest::SetResponseStatusAndString(
153     net::HttpStatusCode status_code,
154     const std::string& response_data) {
155   net::TestURLFetcher* fetcher =
156       url_fetcher_factory_.GetFetcherByID(0);
157   ASSERT_TRUE(fetcher);
158   fetcher->set_response_code(status_code);
159   fetcher->SetResponseString(response_data);
160 }
161 
CompleteFetch()162 void CheckinRequestTest::CompleteFetch() {
163   net::TestURLFetcher* fetcher =
164       url_fetcher_factory_.GetFetcherByID(0);
165   ASSERT_TRUE(fetcher);
166   fetcher->delegate()->OnURLFetchComplete(fetcher);
167 }
168 
SetResponse(ResponseScenario response_scenario)169 void CheckinRequestTest::SetResponse(ResponseScenario response_scenario) {
170   checkin_proto::AndroidCheckinResponse response;
171   response.set_stats_ok(true);
172 
173   uint64 android_id = response_scenario == ANDROID_ID_IS_ZER0 ? 0 : kAndroidId;
174   uint64 security_token =
175       response_scenario == SECURITY_TOKEN_IS_ZERO ? 0 : kSecurityToken;
176 
177   if (response_scenario != MISSING_ANDROID_ID)
178     response.set_android_id(android_id);
179 
180   if (response_scenario != MISSING_SECURITY_TOKEN)
181     response.set_security_token(security_token);
182 
183   std::string response_string;
184   response.SerializeToString(&response_string);
185   SetResponseStatusAndString(net::HTTP_OK, response_string);
186 }
187 
TEST_F(CheckinRequestTest,FetcherDataAndURL)188 TEST_F(CheckinRequestTest, FetcherDataAndURL) {
189   CreateRequest(kAndroidId, kSecurityToken);
190   request_->Start();
191 
192   // Get data sent by request.
193   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
194   ASSERT_TRUE(fetcher);
195   EXPECT_EQ(GURL(kCheckinURL), fetcher->GetOriginalURL());
196 
197   checkin_proto::AndroidCheckinRequest request_proto;
198   request_proto.ParseFromString(fetcher->upload_data());
199   EXPECT_EQ(kAndroidId, static_cast<uint64>(request_proto.id()));
200   EXPECT_EQ(kSecurityToken, request_proto.security_token());
201   EXPECT_EQ(chrome_build_proto_.platform(),
202             request_proto.checkin().chrome_build().platform());
203   EXPECT_EQ(chrome_build_proto_.chrome_version(),
204             request_proto.checkin().chrome_build().chrome_version());
205   EXPECT_EQ(chrome_build_proto_.channel(),
206             request_proto.checkin().chrome_build().channel());
207   EXPECT_EQ(2, request_proto.account_cookie_size());
208   EXPECT_EQ(kEmailAddress, request_proto.account_cookie(0));
209   EXPECT_EQ(kTokenValue, request_proto.account_cookie(1));
210 
211 #if defined(CHROME_OS)
212   EXPECT_EQ(checkin_proto::DEVICE_CHROME_OS, request_proto.checkin().type());
213 #else
214   EXPECT_EQ(checkin_proto::DEVICE_CHROME_BROWSER,
215             request_proto.checkin().type());
216 #endif
217 
218   EXPECT_EQ(kSettingsDigest, request_proto.digest());
219 }
220 
TEST_F(CheckinRequestTest,ResponseBodyEmpty)221 TEST_F(CheckinRequestTest, ResponseBodyEmpty) {
222   CreateRequest(0u, 0u);
223   request_->Start();
224 
225   SetResponseStatusAndString(net::HTTP_OK, std::string());
226   CompleteFetch();
227 
228   EXPECT_FALSE(callback_called_);
229 
230   SetResponse(VALID_RESPONSE);
231   CompleteFetch();
232 
233   EXPECT_TRUE(callback_called_);
234   EXPECT_EQ(kAndroidId, android_id_);
235   EXPECT_EQ(kSecurityToken, security_token_);
236 }
237 
TEST_F(CheckinRequestTest,ResponseBodyCorrupted)238 TEST_F(CheckinRequestTest, ResponseBodyCorrupted) {
239   CreateRequest(0u, 0u);
240   request_->Start();
241 
242   SetResponseStatusAndString(net::HTTP_OK, "Corrupted response body");
243   CompleteFetch();
244 
245   EXPECT_FALSE(callback_called_);
246 
247   SetResponse(VALID_RESPONSE);
248   CompleteFetch();
249 
250   EXPECT_TRUE(callback_called_);
251   EXPECT_EQ(kAndroidId, android_id_);
252   EXPECT_EQ(kSecurityToken, security_token_);
253 }
254 
TEST_F(CheckinRequestTest,ResponseHttpStatusUnauthorized)255 TEST_F(CheckinRequestTest, ResponseHttpStatusUnauthorized) {
256   CreateRequest(0u, 0u);
257   request_->Start();
258 
259   SetResponseStatusAndString(net::HTTP_UNAUTHORIZED, std::string());
260   CompleteFetch();
261 
262   EXPECT_TRUE(callback_called_);
263   EXPECT_EQ(kBlankAndroidId, android_id_);
264   EXPECT_EQ(kBlankSecurityToken, security_token_);
265 }
266 
TEST_F(CheckinRequestTest,ResponseHttpStatusBadRequest)267 TEST_F(CheckinRequestTest, ResponseHttpStatusBadRequest) {
268   CreateRequest(0u, 0u);
269   request_->Start();
270 
271   SetResponseStatusAndString(net::HTTP_BAD_REQUEST, std::string());
272   CompleteFetch();
273 
274   EXPECT_TRUE(callback_called_);
275   EXPECT_EQ(kBlankAndroidId, android_id_);
276   EXPECT_EQ(kBlankSecurityToken, security_token_);
277 }
278 
TEST_F(CheckinRequestTest,ResponseHttpStatusNotOK)279 TEST_F(CheckinRequestTest, ResponseHttpStatusNotOK) {
280   CreateRequest(0u, 0u);
281   request_->Start();
282 
283   SetResponseStatusAndString(net::HTTP_INTERNAL_SERVER_ERROR, std::string());
284   CompleteFetch();
285 
286   EXPECT_FALSE(callback_called_);
287 
288   SetResponse(VALID_RESPONSE);
289   CompleteFetch();
290 
291   EXPECT_TRUE(callback_called_);
292   EXPECT_EQ(kAndroidId, android_id_);
293   EXPECT_EQ(kSecurityToken, security_token_);
294 }
295 
TEST_F(CheckinRequestTest,ResponseMissingAndroidId)296 TEST_F(CheckinRequestTest, ResponseMissingAndroidId) {
297   CreateRequest(0u, 0u);
298   request_->Start();
299 
300   SetResponse(MISSING_ANDROID_ID);
301   CompleteFetch();
302 
303   EXPECT_FALSE(callback_called_);
304 
305   SetResponse(VALID_RESPONSE);
306   CompleteFetch();
307 
308   EXPECT_TRUE(callback_called_);
309   EXPECT_EQ(kAndroidId, android_id_);
310   EXPECT_EQ(kSecurityToken, security_token_);
311 }
312 
TEST_F(CheckinRequestTest,ResponseMissingSecurityToken)313 TEST_F(CheckinRequestTest, ResponseMissingSecurityToken) {
314   CreateRequest(0u, 0u);
315   request_->Start();
316 
317   SetResponse(MISSING_SECURITY_TOKEN);
318   CompleteFetch();
319 
320   EXPECT_FALSE(callback_called_);
321 
322   SetResponse(VALID_RESPONSE);
323   CompleteFetch();
324 
325   EXPECT_TRUE(callback_called_);
326   EXPECT_EQ(kAndroidId, android_id_);
327   EXPECT_EQ(kSecurityToken, security_token_);
328 }
329 
TEST_F(CheckinRequestTest,AndroidIdEqualsZeroInResponse)330 TEST_F(CheckinRequestTest, AndroidIdEqualsZeroInResponse) {
331   CreateRequest(0u, 0u);
332   request_->Start();
333 
334   SetResponse(ANDROID_ID_IS_ZER0);
335   CompleteFetch();
336 
337   EXPECT_FALSE(callback_called_);
338 
339   SetResponse(VALID_RESPONSE);
340   CompleteFetch();
341 
342   EXPECT_TRUE(callback_called_);
343   EXPECT_EQ(kAndroidId, android_id_);
344   EXPECT_EQ(kSecurityToken, security_token_);
345 }
346 
TEST_F(CheckinRequestTest,SecurityTokenEqualsZeroInResponse)347 TEST_F(CheckinRequestTest, SecurityTokenEqualsZeroInResponse) {
348   CreateRequest(0u, 0u);
349   request_->Start();
350 
351   SetResponse(SECURITY_TOKEN_IS_ZERO);
352   CompleteFetch();
353 
354   EXPECT_FALSE(callback_called_);
355 
356   SetResponse(VALID_RESPONSE);
357   CompleteFetch();
358 
359   EXPECT_TRUE(callback_called_);
360   EXPECT_EQ(kAndroidId, android_id_);
361   EXPECT_EQ(kSecurityToken, security_token_);
362 }
363 
TEST_F(CheckinRequestTest,SuccessfulFirstTimeCheckin)364 TEST_F(CheckinRequestTest, SuccessfulFirstTimeCheckin) {
365   CreateRequest(0u, 0u);
366   request_->Start();
367 
368   SetResponse(VALID_RESPONSE);
369   CompleteFetch();
370 
371   EXPECT_TRUE(callback_called_);
372   EXPECT_EQ(kAndroidId, android_id_);
373   EXPECT_EQ(kSecurityToken, security_token_);
374 }
375 
TEST_F(CheckinRequestTest,SuccessfulSubsequentCheckin)376 TEST_F(CheckinRequestTest, SuccessfulSubsequentCheckin) {
377   CreateRequest(kAndroidId, kSecurityToken);
378   request_->Start();
379 
380   SetResponse(VALID_RESPONSE);
381   CompleteFetch();
382 
383   EXPECT_TRUE(callback_called_);
384   EXPECT_EQ(kAndroidId, android_id_);
385   EXPECT_EQ(kSecurityToken, security_token_);
386 }
387 
388 }  // namespace gcm
389