blob: fb4a1569be804bcc26e5c6a37a1478e91c1306cc [file] [log] [blame]
[email protected]bdc64f92013-10-11 05:08:361// 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
[email protected]e196bef32013-12-03 05:33:135#include "google_apis/drive/request_sender.h"
[email protected]bdc64f92013-10-11 05:08:366
dcheng65600b442014-08-29 13:34:047#include "base/sequenced_task_runner.h"
[email protected]fedaeae2013-10-11 08:35:548#include "base/strings/string_number_conversions.h"
[email protected]e196bef32013-12-03 05:33:139#include "google_apis/drive/base_requests.h"
10#include "google_apis/drive/dummy_auth_service.h"
[email protected]bdc64f92013-10-11 05:08:3611#include "testing/gtest/include/gtest/gtest.h"
12
13namespace google_apis {
14
15namespace {
16
[email protected]fedaeae2013-10-11 08:35:5417const char kTestRefreshToken[] = "valid-refresh-token";
18const char kTestAccessToken[] = "valid-access-token";
19
20// Enum for indicating the reason why a request is finished.
21enum FinishReason {
22 NONE,
23 SUCCESS,
24 CANCEL,
25 AUTH_FAILURE,
26};
27
28// AuthService for testing purpose. It accepts kTestRefreshToken and returns
29// kTestAccessToken + {"1", "2", "3", ...}.
30class TestAuthService : public DummyAuthService {
31 public:
32 TestAuthService() : auth_try_count_(0) {}
33
dchengf93bb582014-10-21 16:11:5634 void StartAuthentication(const AuthStatusCallback& callback) override {
[email protected]b8aca8132013-10-11 15:57:4035 // RequestSender should clear the rejected access token before starting
36 // to request another one.
37 EXPECT_FALSE(HasAccessToken());
38
[email protected]fedaeae2013-10-11 08:35:5439 ++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.
[email protected]bdc64f92013-10-11 05:08:3657class RequestSenderTest : public testing::Test {
58 protected:
59 RequestSenderTest()
[email protected]fedaeae2013-10-11 08:35:5460 : 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);
[email protected]bdc64f92013-10-11 05:08:3664 }
65
[email protected]fedaeae2013-10-11 08:35:5466 TestAuthService* auth_service_; // Owned by |request_sender_|.
[email protected]bdc64f92013-10-11 05:08:3667 RequestSender request_sender_;
68};
69
70// Minimal implementation for AuthenticatedRequestInterface that can interact
71// with RequestSender correctly.
72class TestRequest : public AuthenticatedRequestInterface {
73 public:
[email protected]fedaeae2013-10-11 08:35:5474 TestRequest(RequestSender* sender,
75 bool* start_called,
76 FinishReason* finish_reason)
[email protected]bdc64f92013-10-11 05:08:3677 : sender_(sender),
78 start_called_(start_called),
[email protected]fedaeae2013-10-11 08:35:5479 finish_reason_(finish_reason),
[email protected]bdc64f92013-10-11 05:08:3680 weak_ptr_factory_(this) {
81 }
82
83 // Test the situation that the request has finished.
[email protected]fedaeae2013-10-11 08:35:5484 void FinishRequestWithSuccess() {
85 *finish_reason_ = SUCCESS;
[email protected]bdc64f92013-10-11 05:08:3686 sender_->RequestFinished(this);
87 }
88
[email protected]fedaeae2013-10-11 08:35:5489 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
dchengf93bb582014-10-21 16:11:5697 void Start(const std::string& access_token,
98 const std::string& custom_user_agent,
99 const ReAuthenticateCallback& callback) override {
[email protected]bdc64f92013-10-11 05:08:36100 *start_called_ = true;
[email protected]fedaeae2013-10-11 08:35:54101 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.
[email protected]bdc64f92013-10-11 05:08:36106 }
107
dchengf93bb582014-10-21 16:11:56108 void Cancel() override {
[email protected]bdc64f92013-10-11 05:08:36109 EXPECT_TRUE(*start_called_);
[email protected]fedaeae2013-10-11 08:35:54110 *finish_reason_ = CANCEL;
[email protected]bdc64f92013-10-11 05:08:36111 sender_->RequestFinished(this);
112 }
113
satorux1e04b422015-01-29 07:50:53114 void OnAuthFailed(DriveApiErrorCode code) override {
[email protected]fedaeae2013-10-11 08:35:54115 *finish_reason_ = AUTH_FAILURE;
116 sender_->RequestFinished(this);
117 }
[email protected]bdc64f92013-10-11 05:08:36118
dchengf93bb582014-10-21 16:11:56119 base::WeakPtr<AuthenticatedRequestInterface> GetWeakPtr() override {
[email protected]bdc64f92013-10-11 05:08:36120 return weak_ptr_factory_.GetWeakPtr();
121 }
122
123 private:
124 RequestSender* sender_;
125 bool* start_called_;
[email protected]fedaeae2013-10-11 08:35:54126 FinishReason* finish_reason_;
127 std::string passed_access_token_;
128 ReAuthenticateCallback passed_reauth_callback_;
[email protected]bdc64f92013-10-11 05:08:36129 base::WeakPtrFactory<TestRequest> weak_ptr_factory_;
130};
131
132} // namespace
133
134TEST_F(RequestSenderTest, StartAndFinishRequest) {
135 bool start_called = false;
[email protected]fedaeae2013-10-11 08:35:54136 FinishReason finish_reason = NONE;
[email protected]bdc64f92013-10-11 05:08:36137 TestRequest* request = new TestRequest(&request_sender_,
138 &start_called,
[email protected]fedaeae2013-10-11 08:35:54139 &finish_reason);
[email protected]bdc64f92013-10-11 05:08:36140 base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
141
mtomasza8a2de42015-06-30 08:41:43142 base::Closure cancel_closure =
143 request_sender_.StartRequestWithAuthRetry(request);
[email protected]bdc64f92013-10-11 05:08:36144 EXPECT_TRUE(!cancel_closure.is_null());
[email protected]bdc64f92013-10-11 05:08:36145
[email protected]fedaeae2013-10-11 08:35:54146 // 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();
[email protected]bdc64f92013-10-11 05:08:36150 EXPECT_FALSE(weak_ptr); // The request object is deleted.
151
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();
[email protected]fedaeae2013-10-11 08:35:54155 EXPECT_EQ(SUCCESS, finish_reason);
[email protected]bdc64f92013-10-11 05:08:36156}
157
158TEST_F(RequestSenderTest, StartAndCancelRequest) {
159 bool start_called = false;
[email protected]fedaeae2013-10-11 08:35:54160 FinishReason finish_reason = NONE;
[email protected]bdc64f92013-10-11 05:08:36161 TestRequest* request = new TestRequest(&request_sender_,
162 &start_called,
[email protected]fedaeae2013-10-11 08:35:54163 &finish_reason);
[email protected]bdc64f92013-10-11 05:08:36164 base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
165
mtomasza8a2de42015-06-30 08:41:43166 base::Closure cancel_closure =
167 request_sender_.StartRequestWithAuthRetry(request);
[email protected]bdc64f92013-10-11 05:08:36168 EXPECT_TRUE(!cancel_closure.is_null());
169 EXPECT_TRUE(start_called);
170
171 cancel_closure.Run();
[email protected]fedaeae2013-10-11 08:35:54172 EXPECT_EQ(CANCEL, finish_reason);
[email protected]bdc64f92013-10-11 05:08:36173 EXPECT_FALSE(weak_ptr); // The request object is deleted.
174}
175
[email protected]fedaeae2013-10-11 08:35:54176TEST_F(RequestSenderTest, NoRefreshToken) {
177 auth_service_->ClearRefreshToken();
178 auth_service_->ClearAccessToken();
179
180 bool start_called = false;
181 FinishReason finish_reason = NONE;
182 TestRequest* request = new TestRequest(&request_sender_,
183 &start_called,
184 &finish_reason);
185 base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
186
mtomasza8a2de42015-06-30 08:41:43187 base::Closure cancel_closure =
188 request_sender_.StartRequestWithAuthRetry(request);
[email protected]fedaeae2013-10-11 08:35:54189 EXPECT_TRUE(!cancel_closure.is_null());
190
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.
195}
196
197TEST_F(RequestSenderTest, ValidRefreshTokenAndNoAccessToken) {
198 auth_service_->ClearAccessToken();
199
200 bool start_called = false;
201 FinishReason finish_reason = NONE;
202 TestRequest* request = new TestRequest(&request_sender_,
203 &start_called,
204 &finish_reason);
205 base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
206
mtomasza8a2de42015-06-30 08:41:43207 base::Closure cancel_closure =
208 request_sender_.StartRequestWithAuthRetry(request);
[email protected]fedaeae2013-10-11 08:35:54209 EXPECT_TRUE(!cancel_closure.is_null());
210
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.
218}
219
[email protected]b8aca8132013-10-11 15:57:40220TEST_F(RequestSenderTest, AccessTokenRejectedSeveralTimes) {
221 bool start_called = false;
222 FinishReason finish_reason = NONE;
223 TestRequest* request = new TestRequest(&request_sender_,
224 &start_called,
225 &finish_reason);
226 base::WeakPtr<AuthenticatedRequestInterface> weak_ptr = request->GetWeakPtr();
[email protected]fedaeae2013-10-11 08:35:54227
mtomasza8a2de42015-06-30 08:41:43228 base::Closure cancel_closure =
229 request_sender_.StartRequestWithAuthRetry(request);
[email protected]b8aca8132013-10-11 15:57:40230 EXPECT_TRUE(!cancel_closure.is_null());
231
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);
240 // Once more.
241 EXPECT_EQ(kTestAccessToken + std::string("2"),
242 request->passed_access_token());
243 request->passed_reauth_callback().Run(request);
244
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);
[email protected]fedaeae2013-10-11 08:35:54253}
254
[email protected]bdc64f92013-10-11 05:08:36255} // namespace google_apis