files_list_request_runner_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. // Copyright 2015 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/drive/files_list_request_runner.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback.h"
  9. #include "base/run_loop.h"
  10. #include "base/strings/string_number_conversions.h"
  11. #include "base/task/sequenced_task_runner.h"
  12. #include "base/test/task_environment.h"
  13. #include "base/threading/thread_task_runner_handle.h"
  14. #include "google_apis/common/dummy_auth_service.h"
  15. #include "google_apis/common/request_sender.h"
  16. #include "google_apis/drive/drive_base_requests.h"
  17. #include "mojo/public/cpp/bindings/pending_remote.h"
  18. #include "mojo/public/cpp/bindings/remote.h"
  19. #include "net/test/embedded_test_server/embedded_test_server.h"
  20. #include "net/test/embedded_test_server/http_request.h"
  21. #include "net/test/embedded_test_server/http_response.h"
  22. #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
  23. #include "services/network/network_service.h"
  24. #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
  25. #include "services/network/public/mojom/network_context.mojom.h"
  26. #include "services/network/test/fake_test_cert_verifier_params_factory.h"
  27. #include "services/network/test/test_url_loader_factory.h"
  28. #include "testing/gtest/include/gtest/gtest.h"
  29. namespace google_apis {
  30. namespace {
  31. const int kMaxResults = 4;
  32. const char kQuery[] = "testing-query";
  33. const char kFields[] = "testing-fields";
  34. const char kTestUserAgent[] = "test-user-agent";
  35. const char kSuccessResource[] =
  36. "{\n"
  37. " \"kind\": \"drive#fileList\",\n"
  38. " \"etag\": \"etag\",\n"
  39. " \"items\": []\n"
  40. "}\n";
  41. const char kResponseTooLargeErrorResource[] =
  42. "{\n"
  43. " \"error\": {\n"
  44. " \"errors\": [\n"
  45. " {\n"
  46. " \"reason\": \"responseTooLarge\"\n"
  47. " }\n"
  48. " ]\n"
  49. " }\n"
  50. "}\n";
  51. const char kQuotaExceededErrorResource[] =
  52. "{\n"
  53. " \"error\": {\n"
  54. " \"errors\": [\n"
  55. " {\n"
  56. " \"reason\": \"quotaExceeded\"\n"
  57. " }\n"
  58. " ]\n"
  59. " }\n"
  60. "}\n";
  61. } // namespace
  62. class FilesListRequestRunnerTest : public testing::Test {
  63. public:
  64. FilesListRequestRunnerTest() {
  65. mojo::Remote<network::mojom::NetworkService> network_service_remote;
  66. network_service_ = network::NetworkService::Create(
  67. network_service_remote.BindNewPipeAndPassReceiver());
  68. network::mojom::NetworkContextParamsPtr context_params =
  69. network::mojom::NetworkContextParams::New();
  70. // Use a dummy CertVerifier that always passes cert verification, since
  71. // these unittests don't need to test CertVerifier behavior.
  72. context_params->cert_verifier_params =
  73. network::FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
  74. network_service_remote->CreateNetworkContext(
  75. network_context_.BindNewPipeAndPassReceiver(),
  76. std::move(context_params));
  77. mojo::PendingReceiver<network::mojom::URLLoaderNetworkServiceObserver>
  78. default_observer_receiver;
  79. network::mojom::NetworkServiceParamsPtr network_service_params =
  80. network::mojom::NetworkServiceParams::New();
  81. network_service_params->default_observer =
  82. default_observer_receiver.InitWithNewPipeAndPassRemote();
  83. network_service_remote->SetParams(std::move(network_service_params));
  84. network::mojom::URLLoaderFactoryParamsPtr params =
  85. network::mojom::URLLoaderFactoryParams::New();
  86. params->process_id = network::mojom::kBrowserProcessId;
  87. params->is_corb_enabled = false;
  88. network_context_->CreateURLLoaderFactory(
  89. url_loader_factory_.BindNewPipeAndPassReceiver(), std::move(params));
  90. test_shared_loader_factory_ =
  91. base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
  92. url_loader_factory_.get());
  93. }
  94. void SetUp() override {
  95. request_sender_ = std::make_unique<RequestSender>(
  96. std::make_unique<DummyAuthService>(), test_shared_loader_factory_,
  97. task_environment_.GetMainThreadTaskRunner(), kTestUserAgent,
  98. TRAFFIC_ANNOTATION_FOR_TESTS);
  99. test_server_.RegisterRequestHandler(
  100. base::BindRepeating(&FilesListRequestRunnerTest::OnFilesListRequest,
  101. base::Unretained(this), test_server_.base_url()));
  102. ASSERT_TRUE(test_server_.Start());
  103. runner_ = std::make_unique<FilesListRequestRunner>(
  104. request_sender_.get(),
  105. google_apis::DriveApiUrlGenerator(test_server_.base_url(),
  106. test_server_.GetURL("/thumbnail/")));
  107. }
  108. void TearDown() override {
  109. on_completed_callback_ = base::OnceClosure();
  110. http_request_.reset();
  111. response_error_.reset();
  112. response_entry_.reset();
  113. }
  114. // Called when the request is completed and no more backoff retries will
  115. // happen.
  116. void OnCompleted(ApiErrorCode error, std::unique_ptr<FileList> entry) {
  117. response_error_ = std::make_unique<ApiErrorCode>(error);
  118. response_entry_ = std::move(entry);
  119. std::move(on_completed_callback_).Run();
  120. }
  121. protected:
  122. // Sets a fake Drive API server response to be returned for the upcoming HTTP
  123. // request.
  124. void SetFakeServerResponse(net::HttpStatusCode code,
  125. const std::string& content) {
  126. fake_server_response_ =
  127. std::make_unique<net::test_server::BasicHttpResponse>();
  128. fake_server_response_->set_code(code);
  129. fake_server_response_->set_content(content);
  130. fake_server_response_->set_content_type("application/json");
  131. }
  132. // Handles a HTTP request to the Drive API server and returns a fake response.
  133. std::unique_ptr<net::test_server::HttpResponse> OnFilesListRequest(
  134. const GURL& base_url,
  135. const net::test_server::HttpRequest& request) {
  136. http_request_ = std::make_unique<net::test_server::HttpRequest>(request);
  137. return std::move(fake_server_response_);
  138. }
  139. base::test::TaskEnvironment task_environment_{
  140. base::test::TaskEnvironment::MainThreadType::IO};
  141. std::unique_ptr<RequestSender> request_sender_;
  142. net::EmbeddedTestServer test_server_;
  143. std::unique_ptr<FilesListRequestRunner> runner_;
  144. std::unique_ptr<network::mojom::NetworkService> network_service_;
  145. mojo::Remote<network::mojom::NetworkContext> network_context_;
  146. mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory_;
  147. scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
  148. test_shared_loader_factory_;
  149. base::OnceClosure on_completed_callback_;
  150. // Response set by test cases to be returned from the HTTP server.
  151. std::unique_ptr<net::test_server::BasicHttpResponse> fake_server_response_;
  152. // A requests and a response stored for verification in test cases.
  153. std::unique_ptr<net::test_server::HttpRequest> http_request_;
  154. std::unique_ptr<ApiErrorCode> response_error_;
  155. std::unique_ptr<FileList> response_entry_;
  156. };
  157. TEST_F(FilesListRequestRunnerTest, Success_NoBackoff) {
  158. SetFakeServerResponse(net::HTTP_OK, kSuccessResource);
  159. runner_->CreateAndStartWithSizeBackoff(
  160. kMaxResults, FilesListCorpora::DEFAULT, std::string(), kQuery, kFields,
  161. base::BindOnce(&FilesListRequestRunnerTest::OnCompleted,
  162. base::Unretained(this)));
  163. base::RunLoop run_loop;
  164. on_completed_callback_ = run_loop.QuitClosure();
  165. run_loop.Run();
  166. ASSERT_TRUE(http_request_.get());
  167. EXPECT_EQ(
  168. "/drive/v2/files?supportsTeamDrives=true&includeTeamDriveItems=true"
  169. "&corpora=default&maxResults=4&q=testing-query&fields=testing-fields",
  170. http_request_->relative_url);
  171. ASSERT_TRUE(response_error_.get());
  172. EXPECT_EQ(HTTP_SUCCESS, *response_error_);
  173. EXPECT_TRUE(response_entry_.get());
  174. }
  175. TEST_F(FilesListRequestRunnerTest, Success_Backoff) {
  176. SetFakeServerResponse(net::HTTP_INTERNAL_SERVER_ERROR,
  177. kResponseTooLargeErrorResource);
  178. runner_->CreateAndStartWithSizeBackoff(
  179. kMaxResults, FilesListCorpora::DEFAULT, std::string(), kQuery, kFields,
  180. base::BindOnce(&FilesListRequestRunnerTest::OnCompleted,
  181. base::Unretained(this)));
  182. {
  183. base::RunLoop run_loop;
  184. runner_->SetRequestCompletedCallbackForTesting(run_loop.QuitClosure());
  185. run_loop.Run();
  186. ASSERT_TRUE(http_request_.get());
  187. EXPECT_EQ(
  188. "/drive/v2/files?supportsTeamDrives=true&includeTeamDriveItems=true"
  189. "&corpora=default&maxResults=4&q=testing-query&fields=testing-fields",
  190. http_request_->relative_url);
  191. EXPECT_FALSE(response_error_.get());
  192. }
  193. // Backoff will decreasing the number of results by 2, which will succeed.
  194. {
  195. SetFakeServerResponse(net::HTTP_OK, kSuccessResource);
  196. base::RunLoop run_loop;
  197. on_completed_callback_ = run_loop.QuitClosure();
  198. run_loop.Run();
  199. ASSERT_TRUE(http_request_.get());
  200. EXPECT_EQ(
  201. "/drive/v2/files?supportsTeamDrives=true&includeTeamDriveItems=true"
  202. "&corpora=default&maxResults=2&q=testing-query&fields=testing-fields",
  203. http_request_->relative_url);
  204. ASSERT_TRUE(response_error_.get());
  205. EXPECT_EQ(HTTP_SUCCESS, *response_error_);
  206. EXPECT_TRUE(response_entry_.get());
  207. }
  208. }
  209. TEST_F(FilesListRequestRunnerTest, Failure_TooManyBackoffs) {
  210. SetFakeServerResponse(net::HTTP_INTERNAL_SERVER_ERROR,
  211. kResponseTooLargeErrorResource);
  212. runner_->CreateAndStartWithSizeBackoff(
  213. kMaxResults, FilesListCorpora::DEFAULT, std::string(), kQuery, kFields,
  214. base::BindOnce(&FilesListRequestRunnerTest::OnCompleted,
  215. base::Unretained(this)));
  216. {
  217. base::RunLoop run_loop;
  218. runner_->SetRequestCompletedCallbackForTesting(run_loop.QuitClosure());
  219. run_loop.Run();
  220. ASSERT_TRUE(http_request_.get());
  221. EXPECT_EQ(
  222. "/drive/v2/files?supportsTeamDrives=true&includeTeamDriveItems=true"
  223. "&corpora=default&maxResults=4&q=testing-query&fields=testing-fields",
  224. http_request_->relative_url);
  225. EXPECT_FALSE(response_error_.get());
  226. }
  227. // Backoff will decreasing the number of results by 2, which will still fail
  228. // due to too large response.
  229. {
  230. SetFakeServerResponse(net::HTTP_INTERNAL_SERVER_ERROR,
  231. kResponseTooLargeErrorResource);
  232. base::RunLoop run_loop;
  233. runner_->SetRequestCompletedCallbackForTesting(run_loop.QuitClosure());
  234. run_loop.Run();
  235. ASSERT_TRUE(http_request_.get());
  236. EXPECT_EQ(
  237. "/drive/v2/files?supportsTeamDrives=true&includeTeamDriveItems=true"
  238. "&corpora=default&maxResults=2&q=testing-query&fields=testing-fields",
  239. http_request_->relative_url);
  240. EXPECT_FALSE(response_error_.get());
  241. }
  242. // The last backoff, decreasing the number of results to 1.
  243. {
  244. SetFakeServerResponse(net::HTTP_INTERNAL_SERVER_ERROR,
  245. kResponseTooLargeErrorResource);
  246. base::RunLoop run_loop;
  247. on_completed_callback_ = run_loop.QuitClosure();
  248. run_loop.Run();
  249. ASSERT_TRUE(http_request_.get());
  250. EXPECT_EQ(
  251. "/drive/v2/files?supportsTeamDrives=true&includeTeamDriveItems=true"
  252. "&corpora=default&maxResults=1&q=testing-query&fields=testing-fields",
  253. http_request_->relative_url);
  254. ASSERT_TRUE(response_error_.get());
  255. EXPECT_EQ(DRIVE_RESPONSE_TOO_LARGE, *response_error_);
  256. EXPECT_FALSE(response_entry_.get());
  257. }
  258. }
  259. TEST_F(FilesListRequestRunnerTest, Failure_AnotherError) {
  260. SetFakeServerResponse(net::HTTP_INTERNAL_SERVER_ERROR,
  261. kQuotaExceededErrorResource);
  262. runner_->CreateAndStartWithSizeBackoff(
  263. kMaxResults, FilesListCorpora::DEFAULT, std::string(), kQuery, kFields,
  264. base::BindOnce(&FilesListRequestRunnerTest::OnCompleted,
  265. base::Unretained(this)));
  266. base::RunLoop run_loop;
  267. on_completed_callback_ = run_loop.QuitClosure();
  268. run_loop.Run();
  269. ASSERT_TRUE(http_request_.get());
  270. EXPECT_EQ(
  271. "/drive/v2/files?supportsTeamDrives=true&includeTeamDriveItems=true"
  272. "&corpora=default&maxResults=4&q=testing-query&fields=testing-fields",
  273. http_request_->relative_url);
  274. // There must be no backoff in case of an error different than
  275. // DRIVE_RESPONSE_TOO_LARGE.
  276. ASSERT_TRUE(response_error_.get());
  277. EXPECT_EQ(DRIVE_NO_SPACE, *response_error_);
  278. EXPECT_FALSE(response_entry_.get());
  279. }
  280. } // namespace google_apis