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.
5 #include "google_apis/drive/request_sender.h"
7 #include "base/sequenced_task_runner.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "google_apis/drive/base_requests.h"
10 #include "google_apis/drive/dummy_auth_service.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 namespace google_apis
{
17 const char kTestRefreshToken
[] = "valid-refresh-token";
18 const char kTestAccessToken
[] = "valid-access-token";
20 // Enum for indicating the reason why a request is finished.
28 // AuthService for testing purpose. It accepts kTestRefreshToken and returns
29 // kTestAccessToken + {"1", "2", "3", ...}.
30 class TestAuthService
: public DummyAuthService
{
32 TestAuthService() : auth_try_count_(0) {}
34 void StartAuthentication(const AuthStatusCallback
& callback
) override
{
35 // RequestSender should clear the rejected access token before starting
36 // to request another one.
37 EXPECT_FALSE(HasAccessToken());
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
);
48 callback
.Run(HTTP_UNAUTHORIZED
, "");
56 // The main test fixture class.
57 class RequestSenderTest
: public testing::Test
{
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
);
66 TestAuthService
* auth_service_
; // Owned by |request_sender_|.
67 RequestSender request_sender_
;
70 // Minimal implementation for AuthenticatedRequestInterface that can interact
71 // with RequestSender correctly.
72 class TestRequest
: public AuthenticatedRequestInterface
{
74 TestRequest(RequestSender
* sender
,
76 FinishReason
* finish_reason
)
78 start_called_(start_called
),
79 finish_reason_(finish_reason
),
80 weak_ptr_factory_(this) {
83 // Test the situation that the request has finished.
84 void FinishRequestWithSuccess() {
85 *finish_reason_
= SUCCESS
;
86 sender_
->RequestFinished(this);
89 const std::string
& passed_access_token() const {
90 return passed_access_token_
;
93 const ReAuthenticateCallback
& passed_reauth_callback() const {
94 return passed_reauth_callback_
;
97 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
;
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.
108 void Cancel() override
{
109 EXPECT_TRUE(*start_called_
);
110 *finish_reason_
= CANCEL
;
111 sender_
->RequestFinished(this);
114 void OnAuthFailed(DriveApiErrorCode code
) override
{
115 *finish_reason_
= AUTH_FAILURE
;
116 sender_
->RequestFinished(this);
119 base::WeakPtr
<AuthenticatedRequestInterface
> GetWeakPtr() override
{
120 return weak_ptr_factory_
.GetWeakPtr();
124 RequestSender
* sender_
;
126 FinishReason
* finish_reason_
;
127 std::string passed_access_token_
;
128 ReAuthenticateCallback passed_reauth_callback_
;
129 base::WeakPtrFactory
<TestRequest
> weak_ptr_factory_
;
134 TEST_F(RequestSenderTest
, StartAndFinishRequest
) {
135 bool start_called
= false;
136 FinishReason finish_reason
= NONE
;
137 TestRequest
* request
= new TestRequest(&request_sender_
,
140 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
142 base::Closure cancel_closure
=
143 request_sender_
.StartRequestWithAuthRetry(request
);
144 EXPECT_TRUE(!cancel_closure
.is_null());
146 // Start is called with the specified access token. Let it succeed.
147 EXPECT_TRUE(start_called
);
148 EXPECT_EQ(kTestAccessToken
, request
->passed_access_token());
149 request
->FinishRequestWithSuccess();
150 EXPECT_FALSE(weak_ptr
); // The request object is deleted.
152 // It is safe to run the cancel closure even after the request is finished.
153 // It is just no-op. The TestRequest::Cancel method is not called.
154 cancel_closure
.Run();
155 EXPECT_EQ(SUCCESS
, finish_reason
);
158 TEST_F(RequestSenderTest
, StartAndCancelRequest
) {
159 bool start_called
= false;
160 FinishReason finish_reason
= NONE
;
161 TestRequest
* request
= new TestRequest(&request_sender_
,
164 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
166 base::Closure cancel_closure
=
167 request_sender_
.StartRequestWithAuthRetry(request
);
168 EXPECT_TRUE(!cancel_closure
.is_null());
169 EXPECT_TRUE(start_called
);
171 cancel_closure
.Run();
172 EXPECT_EQ(CANCEL
, finish_reason
);
173 EXPECT_FALSE(weak_ptr
); // The request object is deleted.
176 TEST_F(RequestSenderTest
, NoRefreshToken
) {
177 auth_service_
->ClearRefreshToken();
178 auth_service_
->ClearAccessToken();
180 bool start_called
= false;
181 FinishReason finish_reason
= NONE
;
182 TestRequest
* request
= new TestRequest(&request_sender_
,
185 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
187 base::Closure cancel_closure
=
188 request_sender_
.StartRequestWithAuthRetry(request
);
189 EXPECT_TRUE(!cancel_closure
.is_null());
191 // The request is not started at all because no access token is obtained.
192 EXPECT_FALSE(start_called
);
193 EXPECT_EQ(AUTH_FAILURE
, finish_reason
);
194 EXPECT_FALSE(weak_ptr
); // The request object is deleted.
197 TEST_F(RequestSenderTest
, ValidRefreshTokenAndNoAccessToken
) {
198 auth_service_
->ClearAccessToken();
200 bool start_called
= false;
201 FinishReason finish_reason
= NONE
;
202 TestRequest
* request
= new TestRequest(&request_sender_
,
205 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
207 base::Closure cancel_closure
=
208 request_sender_
.StartRequestWithAuthRetry(request
);
209 EXPECT_TRUE(!cancel_closure
.is_null());
211 // Access token should indicate that this is the first retry.
212 EXPECT_TRUE(start_called
);
213 EXPECT_EQ(kTestAccessToken
+ std::string("1"),
214 request
->passed_access_token());
215 request
->FinishRequestWithSuccess();
216 EXPECT_EQ(SUCCESS
, finish_reason
);
217 EXPECT_FALSE(weak_ptr
); // The request object is deleted.
220 TEST_F(RequestSenderTest
, AccessTokenRejectedSeveralTimes
) {
221 bool start_called
= false;
222 FinishReason finish_reason
= NONE
;
223 TestRequest
* request
= new TestRequest(&request_sender_
,
226 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
228 base::Closure cancel_closure
=
229 request_sender_
.StartRequestWithAuthRetry(request
);
230 EXPECT_TRUE(!cancel_closure
.is_null());
232 EXPECT_TRUE(start_called
);
233 EXPECT_EQ(kTestAccessToken
, request
->passed_access_token());
234 // Emulate the case that the access token was rejected by the remote service.
235 request
->passed_reauth_callback().Run(request
);
236 // New access token is fetched. Let it fail once again.
237 EXPECT_EQ(kTestAccessToken
+ std::string("1"),
238 request
->passed_access_token());
239 request
->passed_reauth_callback().Run(request
);
241 EXPECT_EQ(kTestAccessToken
+ std::string("2"),
242 request
->passed_access_token());
243 request
->passed_reauth_callback().Run(request
);
245 // Currently, limit for the retry is controlled in each request object, not
246 // by the RequestSender. So with this TestRequest, RequestSender retries
247 // infinitely. Let it succeed/
248 EXPECT_EQ(kTestAccessToken
+ std::string("3"),
249 request
->passed_access_token());
250 request
->FinishRequestWithSuccess();
251 EXPECT_EQ(SUCCESS
, finish_reason
);
252 EXPECT_FALSE(weak_ptr
);
255 } // namespace google_apis