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 virtual void StartAuthentication(
35 const AuthStatusCallback
& callback
) override
{
36 // RequestSender should clear the rejected access token before starting
37 // to request another one.
38 EXPECT_FALSE(HasAccessToken());
42 if (refresh_token() == kTestRefreshToken
) {
43 const std::string token
=
44 kTestAccessToken
+ base::IntToString(auth_try_count_
);
45 set_access_token(token
);
46 callback
.Run(HTTP_SUCCESS
, token
);
49 callback
.Run(HTTP_UNAUTHORIZED
, "");
57 // The main test fixture class.
58 class RequestSenderTest
: public testing::Test
{
61 : auth_service_(new TestAuthService
),
62 request_sender_(auth_service_
, NULL
, NULL
, "dummy-user-agent") {
63 auth_service_
->set_refresh_token(kTestRefreshToken
);
64 auth_service_
->set_access_token(kTestAccessToken
);
67 TestAuthService
* auth_service_
; // Owned by |request_sender_|.
68 RequestSender request_sender_
;
71 // Minimal implementation for AuthenticatedRequestInterface that can interact
72 // with RequestSender correctly.
73 class TestRequest
: public AuthenticatedRequestInterface
{
75 TestRequest(RequestSender
* sender
,
77 FinishReason
* finish_reason
)
79 start_called_(start_called
),
80 finish_reason_(finish_reason
),
81 weak_ptr_factory_(this) {
84 // Test the situation that the request has finished.
85 void FinishRequestWithSuccess() {
86 *finish_reason_
= SUCCESS
;
87 sender_
->RequestFinished(this);
90 const std::string
& passed_access_token() const {
91 return passed_access_token_
;
94 const ReAuthenticateCallback
& passed_reauth_callback() const {
95 return passed_reauth_callback_
;
98 virtual void Start(const std::string
& access_token
,
99 const std::string
& custom_user_agent
,
100 const ReAuthenticateCallback
& callback
) override
{
101 *start_called_
= true;
102 passed_access_token_
= access_token
;
103 passed_reauth_callback_
= callback
;
105 // This request class itself does not return any response at this point.
106 // Each test case should respond properly by using the above methods.
109 virtual void Cancel() override
{
110 EXPECT_TRUE(*start_called_
);
111 *finish_reason_
= CANCEL
;
112 sender_
->RequestFinished(this);
115 virtual void OnAuthFailed(GDataErrorCode code
) override
{
116 *finish_reason_
= AUTH_FAILURE
;
117 sender_
->RequestFinished(this);
120 virtual base::WeakPtr
<AuthenticatedRequestInterface
> GetWeakPtr() override
{
121 return weak_ptr_factory_
.GetWeakPtr();
125 RequestSender
* sender_
;
127 FinishReason
* finish_reason_
;
128 std::string passed_access_token_
;
129 ReAuthenticateCallback passed_reauth_callback_
;
130 base::WeakPtrFactory
<TestRequest
> weak_ptr_factory_
;
135 TEST_F(RequestSenderTest
, StartAndFinishRequest
) {
136 bool start_called
= false;
137 FinishReason finish_reason
= NONE
;
138 TestRequest
* request
= new TestRequest(&request_sender_
,
141 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
143 base::Closure cancel_closure
= request_sender_
.StartRequestWithRetry(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
= request_sender_
.StartRequestWithRetry(request
);
167 EXPECT_TRUE(!cancel_closure
.is_null());
168 EXPECT_TRUE(start_called
);
170 cancel_closure
.Run();
171 EXPECT_EQ(CANCEL
, finish_reason
);
172 EXPECT_FALSE(weak_ptr
); // The request object is deleted.
175 TEST_F(RequestSenderTest
, NoRefreshToken
) {
176 auth_service_
->ClearRefreshToken();
177 auth_service_
->ClearAccessToken();
179 bool start_called
= false;
180 FinishReason finish_reason
= NONE
;
181 TestRequest
* request
= new TestRequest(&request_sender_
,
184 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
186 base::Closure cancel_closure
= request_sender_
.StartRequestWithRetry(request
);
187 EXPECT_TRUE(!cancel_closure
.is_null());
189 // The request is not started at all because no access token is obtained.
190 EXPECT_FALSE(start_called
);
191 EXPECT_EQ(AUTH_FAILURE
, finish_reason
);
192 EXPECT_FALSE(weak_ptr
); // The request object is deleted.
195 TEST_F(RequestSenderTest
, ValidRefreshTokenAndNoAccessToken
) {
196 auth_service_
->ClearAccessToken();
198 bool start_called
= false;
199 FinishReason finish_reason
= NONE
;
200 TestRequest
* request
= new TestRequest(&request_sender_
,
203 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
205 base::Closure cancel_closure
= request_sender_
.StartRequestWithRetry(request
);
206 EXPECT_TRUE(!cancel_closure
.is_null());
208 // Access token should indicate that this is the first retry.
209 EXPECT_TRUE(start_called
);
210 EXPECT_EQ(kTestAccessToken
+ std::string("1"),
211 request
->passed_access_token());
212 request
->FinishRequestWithSuccess();
213 EXPECT_EQ(SUCCESS
, finish_reason
);
214 EXPECT_FALSE(weak_ptr
); // The request object is deleted.
217 TEST_F(RequestSenderTest
, AccessTokenRejectedSeveralTimes
) {
218 bool start_called
= false;
219 FinishReason finish_reason
= NONE
;
220 TestRequest
* request
= new TestRequest(&request_sender_
,
223 base::WeakPtr
<AuthenticatedRequestInterface
> weak_ptr
= request
->GetWeakPtr();
225 base::Closure cancel_closure
= request_sender_
.StartRequestWithRetry(request
);
226 EXPECT_TRUE(!cancel_closure
.is_null());
228 EXPECT_TRUE(start_called
);
229 EXPECT_EQ(kTestAccessToken
, request
->passed_access_token());
230 // Emulate the case that the access token was rejected by the remote service.
231 request
->passed_reauth_callback().Run(request
);
232 // New access token is fetched. Let it fail once again.
233 EXPECT_EQ(kTestAccessToken
+ std::string("1"),
234 request
->passed_access_token());
235 request
->passed_reauth_callback().Run(request
);
237 EXPECT_EQ(kTestAccessToken
+ std::string("2"),
238 request
->passed_access_token());
239 request
->passed_reauth_callback().Run(request
);
241 // Currently, limit for the retry is controlled in each request object, not
242 // by the RequestSender. So with this TestRequest, RequestSender retries
243 // infinitely. Let it succeed/
244 EXPECT_EQ(kTestAccessToken
+ std::string("3"),
245 request
->passed_access_token());
246 request
->FinishRequestWithSuccess();
247 EXPECT_EQ(SUCCESS
, finish_reason
);
248 EXPECT_FALSE(weak_ptr
);
251 } // namespace google_apis