- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / google_apis / request_sender_unittest.cc
1 // Copyright 2013 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 "chrome/browser/google_apis/request_sender.h"
6
7 #include "base/strings/string_number_conversions.h"
8 #include "chrome/browser/google_apis/base_requests.h"
9 #include "chrome/browser/google_apis/dummy_auth_service.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace google_apis {
13
14 namespace {
15
16 const char kTestRefreshToken[] = "valid-refresh-token";
17 const char kTestAccessToken[] = "valid-access-token";
18
19 // Enum for indicating the reason why a request is finished.
20 enum FinishReason {
21   NONE,
22   SUCCESS,
23   CANCEL,
24   AUTH_FAILURE,
25 };
26
27 // AuthService for testing purpose. It accepts kTestRefreshToken and returns
28 // kTestAccessToken + {"1", "2", "3", ...}.
29 class TestAuthService : public DummyAuthService {
30  public:
31   TestAuthService() : auth_try_count_(0) {}
32
33   virtual void StartAuthentication(
34       const AuthStatusCallback& callback) OVERRIDE {
35     // RequestSender should clear the rejected access token before starting
36     // to request another one.
37     EXPECT_FALSE(HasAccessToken());
38
39     ++auth_try_count_;
40
41     if (refresh_token() == kTestRefreshToken) {
42       const std::string token =
43           kTestAccessToken + base::IntToString(auth_try_count_);
44       set_access_token(token);
45       callback.Run(HTTP_SUCCESS, token);
46     } else {
47       set_access_token("");
48       callback.Run(HTTP_UNAUTHORIZED, "");
49     }
50   }
51
52  private:
53   int auth_try_count_;
54 };
55
56 // The main test fixture class.
57 class RequestSenderTest : public testing::Test {
58  protected:
59   RequestSenderTest()
60      : auth_service_(new TestAuthService),
61        request_sender_(auth_service_, NULL, NULL, "dummy-user-agent") {
62     auth_service_->set_refresh_token(kTestRefreshToken);
63     auth_service_->set_access_token(kTestAccessToken);
64   }
65
66   TestAuthService* auth_service_;  // Owned by |request_sender_|.
67   RequestSender request_sender_;
68 };
69
70 // Minimal implementation for AuthenticatedRequestInterface that can interact
71 // with RequestSender correctly.
72 class TestRequest : public AuthenticatedRequestInterface {
73  public:
74   TestRequest(RequestSender* sender,
75               bool* start_called,
76               FinishReason* finish_reason)
77       : sender_(sender),
78         start_called_(start_called),
79         finish_reason_(finish_reason),
80         weak_ptr_factory_(this) {
81   }
82
83   // Test the situation that the request has finished.
84   void FinishRequestWithSuccess() {
85     *finish_reason_ = SUCCESS;
86     sender_->RequestFinished(this);
87   }
88
89   const std::string& passed_access_token() const {
90     return passed_access_token_;
91   }
92
93   const ReAuthenticateCallback& passed_reauth_callback() const {
94     return passed_reauth_callback_;
95   }
96
97   virtual void Start(const std::string& access_token,
98                      const std::string& custom_user_agent,
99                      const ReAuthenticateCallback& callback) OVERRIDE {
100     *start_called_ = true;
101     passed_access_token_ = access_token;
102     passed_reauth_callback_ = callback;
103
104     // This request class itself does not return any response at this point.
105     // Each test case should respond properly by using the above methods.
106   }
107
108   virtual void Cancel() OVERRIDE {
109     EXPECT_TRUE(*start_called_);
110     *finish_reason_ = CANCEL;
111     sender_->RequestFinished(this);
112   }
113
114   virtual void OnAuthFailed(GDataErrorCode code) OVERRIDE {
115     *finish_reason_ = AUTH_FAILURE;
116     sender_->RequestFinished(this);
117   }
118
119   virtual base::WeakPtr<AuthenticatedRequestInterface> GetWeakPtr() OVERRIDE {
120     return weak_ptr_factory_.GetWeakPtr();
121   }
122
123  private:
124   RequestSender* sender_;
125   bool* start_called_;
126   FinishReason* finish_reason_;
127   std::string passed_access_token_;
128   ReAuthenticateCallback passed_reauth_callback_;
129   base::WeakPtrFactory<TestRequest> weak_ptr_factory_;
130 };
131
132 }  // namespace
133
134 TEST_F(RequestSenderTest, StartAndFinishRequest) {
135   bool start_called  = false;
136   FinishReason finish_reason = NONE;
137   TestRequest* request = new TestRequest(&request_sender_,
138                                          &start_called,
139                                          &finish_reason);
140   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
141
142   base::Closure cancel_closure = request_sender_.StartRequestWithRetry(request);
143   EXPECT_TRUE(!cancel_closure.is_null());
144
145   // Start is called with the specified access token. Let it succeed.
146   EXPECT_TRUE(start_called);
147   EXPECT_EQ(kTestAccessToken, request->passed_access_token());
148   request->FinishRequestWithSuccess();
149   EXPECT_FALSE(weak_ptr);  // The request object is deleted.
150
151   // It is safe to run the cancel closure even after the request is finished.
152   // It is just no-op. The TestRequest::Cancel method is not called.
153   cancel_closure.Run();
154   EXPECT_EQ(SUCCESS, finish_reason);
155 }
156
157 TEST_F(RequestSenderTest, StartAndCancelRequest) {
158   bool start_called  = false;
159   FinishReason finish_reason = NONE;
160   TestRequest* request = new TestRequest(&request_sender_,
161                                          &start_called,
162                                          &finish_reason);
163   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
164
165   base::Closure cancel_closure = request_sender_.StartRequestWithRetry(request);
166   EXPECT_TRUE(!cancel_closure.is_null());
167   EXPECT_TRUE(start_called);
168
169   cancel_closure.Run();
170   EXPECT_EQ(CANCEL, finish_reason);
171   EXPECT_FALSE(weak_ptr);  // The request object is deleted.
172 }
173
174 TEST_F(RequestSenderTest, NoRefreshToken) {
175   auth_service_->ClearRefreshToken();
176   auth_service_->ClearAccessToken();
177
178   bool start_called  = false;
179   FinishReason finish_reason = NONE;
180   TestRequest* request = new TestRequest(&request_sender_,
181                                          &start_called,
182                                          &finish_reason);
183   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
184
185   base::Closure cancel_closure = request_sender_.StartRequestWithRetry(request);
186   EXPECT_TRUE(!cancel_closure.is_null());
187
188   // The request is not started at all because no access token is obtained.
189   EXPECT_FALSE(start_called);
190   EXPECT_EQ(AUTH_FAILURE, finish_reason);
191   EXPECT_FALSE(weak_ptr);  // The request object is deleted.
192 }
193
194 TEST_F(RequestSenderTest, ValidRefreshTokenAndNoAccessToken) {
195   auth_service_->ClearAccessToken();
196
197   bool start_called  = false;
198   FinishReason finish_reason = NONE;
199   TestRequest* request = new TestRequest(&request_sender_,
200                                          &start_called,
201                                          &finish_reason);
202   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
203
204   base::Closure cancel_closure = request_sender_.StartRequestWithRetry(request);
205   EXPECT_TRUE(!cancel_closure.is_null());
206
207   // Access token should indicate that this is the first retry.
208   EXPECT_TRUE(start_called);
209   EXPECT_EQ(kTestAccessToken + std::string("1"),
210             request->passed_access_token());
211   request->FinishRequestWithSuccess();
212   EXPECT_EQ(SUCCESS, finish_reason);
213   EXPECT_FALSE(weak_ptr);  // The request object is deleted.
214 }
215
216 TEST_F(RequestSenderTest, AccessTokenRejectedSeveralTimes) {
217   bool start_called  = false;
218   FinishReason finish_reason = NONE;
219   TestRequest* request = new TestRequest(&request_sender_,
220                                          &start_called,
221                                          &finish_reason);
222   base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
223
224   base::Closure cancel_closure = request_sender_.StartRequestWithRetry(request);
225   EXPECT_TRUE(!cancel_closure.is_null());
226
227   EXPECT_TRUE(start_called);
228   EXPECT_EQ(kTestAccessToken, request->passed_access_token());
229   // Emulate the case that the access token was rejected by the remote service.
230   request->passed_reauth_callback().Run(request);
231   // New access token is fetched. Let it fail once again.
232   EXPECT_EQ(kTestAccessToken + std::string("1"),
233             request->passed_access_token());
234   request->passed_reauth_callback().Run(request);
235   // Once more.
236   EXPECT_EQ(kTestAccessToken + std::string("2"),
237             request->passed_access_token());
238   request->passed_reauth_callback().Run(request);
239
240   // Currently, limit for the retry is controlled in each request object, not
241   // by the RequestSender. So with this TestRequest, RequestSender retries
242   // infinitely. Let it succeed/
243   EXPECT_EQ(kTestAccessToken + std::string("3"),
244             request->passed_access_token());
245   request->FinishRequestWithSuccess();
246   EXPECT_EQ(SUCCESS, finish_reason);
247   EXPECT_FALSE(weak_ptr);
248 }
249
250 }  // namespace google_apis