request_sender_unittest.cc 8.9 KB

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