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
= request_sender_
.StartRequestWithRetry(request
);
143 EXPECT_TRUE(!cancel_closure
.is_null());
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.
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
);
157 TEST_F(RequestSenderTest
, StartAndCancelRequest
) {
158 bool start_called
= false;
159 FinishReason finish_reason
= NONE
;
160 TestRequest
* request
= new TestRequest(&request_sender_
,
163 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
165 base::Closure cancel_closure
= request_sender_
.StartRequestWithRetry(request
);
166 EXPECT_TRUE(!cancel_closure
.is_null());
167 EXPECT_TRUE(start_called
);
169 cancel_closure
.Run();
170 EXPECT_EQ(CANCEL
, finish_reason
);
171 EXPECT_FALSE(weak_ptr
); // The request object is deleted.
174 TEST_F(RequestSenderTest
, NoRefreshToken
) {
175 auth_service_
->ClearRefreshToken();
176 auth_service_
->ClearAccessToken();
178 bool start_called
= false;
179 FinishReason finish_reason
= NONE
;
180 TestRequest
* request
= new TestRequest(&request_sender_
,
183 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
185 base::Closure cancel_closure
= request_sender_
.StartRequestWithRetry(request
);
186 EXPECT_TRUE(!cancel_closure
.is_null());
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.
194 TEST_F(RequestSenderTest
, ValidRefreshTokenAndNoAccessToken
) {
195 auth_service_
->ClearAccessToken();
197 bool start_called
= false;
198 FinishReason finish_reason
= NONE
;
199 TestRequest
* request
= new TestRequest(&request_sender_
,
202 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
204 base::Closure cancel_closure
= request_sender_
.StartRequestWithRetry(request
);
205 EXPECT_TRUE(!cancel_closure
.is_null());
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.
216 TEST_F(RequestSenderTest
, AccessTokenRejectedSeveralTimes
) {
217 bool start_called
= false;
218 FinishReason finish_reason
= NONE
;
219 TestRequest
* request
= new TestRequest(&request_sender_
,
222 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
224 base::Closure cancel_closure
= request_sender_
.StartRequestWithRetry(request
);
225 EXPECT_TRUE(!cancel_closure
.is_null());
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
);
236 EXPECT_EQ(kTestAccessToken
+ std::string("2"),
237 request
->passed_access_token());
238 request
->passed_reauth_callback().Run(request
);
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
);
250 } // namespace google_apis