request_sender_unittest.cc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // Copyright 2014 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 "components/update_client/request_sender.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/memory/ref_counted.h"
  9. #include "base/path_service.h"
  10. #include "base/run_loop.h"
  11. #include "base/strings/string_util.h"
  12. #include "base/test/task_environment.h"
  13. #include "base/threading/thread_task_runner_handle.h"
  14. #include "components/update_client/net/url_loader_post_interceptor.h"
  15. #include "components/update_client/test_configurator.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. namespace update_client {
  18. namespace {
  19. const char kUrl1[] = "https://localhost2/path1";
  20. const char kUrl2[] = "https://localhost2/path2";
  21. // TODO(sorin): refactor as a utility function for unit tests.
  22. base::FilePath test_file(const char* file) {
  23. base::FilePath path;
  24. base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
  25. return path.AppendASCII("components")
  26. .AppendASCII("test")
  27. .AppendASCII("data")
  28. .AppendASCII("update_client")
  29. .AppendASCII(file);
  30. }
  31. } // namespace
  32. class RequestSenderTest : public testing::Test,
  33. public ::testing::WithParamInterface<bool> {
  34. public:
  35. RequestSenderTest();
  36. RequestSenderTest(const RequestSenderTest&) = delete;
  37. RequestSenderTest& operator=(const RequestSenderTest&) = delete;
  38. ~RequestSenderTest() override;
  39. // Overrides from testing::Test.
  40. void SetUp() override;
  41. void TearDown() override;
  42. void RequestSenderComplete(int error,
  43. const std::string& response,
  44. int retry_after_sec);
  45. protected:
  46. void Quit();
  47. void RunThreads();
  48. base::test::TaskEnvironment task_environment_;
  49. scoped_refptr<TestConfigurator> config_;
  50. std::unique_ptr<RequestSender> request_sender_;
  51. std::unique_ptr<URLLoaderPostInterceptor> post_interceptor_;
  52. int error_ = 0;
  53. std::string response_;
  54. private:
  55. base::OnceClosure quit_closure_;
  56. };
  57. INSTANTIATE_TEST_SUITE_P(IsForeground, RequestSenderTest, ::testing::Bool());
  58. RequestSenderTest::RequestSenderTest()
  59. : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
  60. RequestSenderTest::~RequestSenderTest() = default;
  61. void RequestSenderTest::SetUp() {
  62. config_ = base::MakeRefCounted<TestConfigurator>();
  63. request_sender_ = std::make_unique<RequestSender>(config_);
  64. std::vector<GURL> urls;
  65. urls.push_back(GURL(kUrl1));
  66. urls.push_back(GURL(kUrl2));
  67. post_interceptor_ = std::make_unique<URLLoaderPostInterceptor>(
  68. urls, config_->test_url_loader_factory());
  69. EXPECT_TRUE(post_interceptor_);
  70. }
  71. void RequestSenderTest::TearDown() {
  72. request_sender_ = nullptr;
  73. post_interceptor_.reset();
  74. // Run the threads until they are idle to allow the clean up
  75. // of the network interceptors on the IO thread.
  76. task_environment_.RunUntilIdle();
  77. config_ = nullptr;
  78. }
  79. void RequestSenderTest::RunThreads() {
  80. base::RunLoop runloop;
  81. quit_closure_ = runloop.QuitClosure();
  82. runloop.Run();
  83. }
  84. void RequestSenderTest::Quit() {
  85. if (!quit_closure_.is_null())
  86. std::move(quit_closure_).Run();
  87. }
  88. void RequestSenderTest::RequestSenderComplete(int error,
  89. const std::string& response,
  90. int retry_after_sec) {
  91. error_ = error;
  92. response_ = response;
  93. Quit();
  94. }
  95. // Tests that when a request to the first url succeeds, the subsequent urls are
  96. // not tried.
  97. TEST_P(RequestSenderTest, RequestSendSuccess) {
  98. EXPECT_TRUE(
  99. post_interceptor_->ExpectRequest(std::make_unique<PartialMatch>("test"),
  100. test_file("updatecheck_reply_1.json")));
  101. const bool is_foreground = GetParam();
  102. request_sender_->Send(
  103. {GURL(kUrl1), GURL(kUrl2)},
  104. {{"X-Goog-Update-Interactivity", is_foreground ? "fg" : "bg"}}, "test",
  105. false,
  106. base::BindOnce(&RequestSenderTest::RequestSenderComplete,
  107. base::Unretained(this)));
  108. RunThreads();
  109. EXPECT_EQ(1, post_interceptor_->GetHitCount())
  110. << post_interceptor_->GetRequestsAsString();
  111. EXPECT_EQ(1, post_interceptor_->GetCount())
  112. << post_interceptor_->GetRequestsAsString();
  113. EXPECT_EQ(0, post_interceptor_->GetHitCountForURL(GURL(kUrl2)))
  114. << post_interceptor_->GetRequestsAsString();
  115. EXPECT_STREQ("test", post_interceptor_->GetRequestBody(0).c_str());
  116. // Check the response post conditions.
  117. EXPECT_EQ(0, error_);
  118. EXPECT_EQ(419ul, response_.size());
  119. // Check the interactivity header value.
  120. const auto extra_request_headers =
  121. std::get<1>(post_interceptor_->GetRequests()[0]);
  122. EXPECT_TRUE(extra_request_headers.HasHeader("X-Goog-Update-Interactivity"));
  123. EXPECT_TRUE(extra_request_headers.HasHeader("Content-Type"));
  124. std::string header;
  125. extra_request_headers.GetHeader("X-Goog-Update-Interactivity", &header);
  126. EXPECT_STREQ(is_foreground ? "fg" : "bg", header.c_str());
  127. extra_request_headers.GetHeader("Content-Type", &header);
  128. EXPECT_STREQ("application/json", header.c_str());
  129. }
  130. // Tests that the request succeeds using the second url after the first url
  131. // has failed.
  132. TEST_F(RequestSenderTest, RequestSendSuccessWithFallback) {
  133. EXPECT_TRUE(post_interceptor_->ExpectRequest(
  134. std::make_unique<PartialMatch>("test"), net::HTTP_FORBIDDEN));
  135. EXPECT_TRUE(
  136. post_interceptor_->ExpectRequest(std::make_unique<PartialMatch>("test")));
  137. request_sender_->Send(
  138. {GURL(kUrl1), GURL(kUrl2)}, {}, "test", false,
  139. base::BindOnce(&RequestSenderTest::RequestSenderComplete,
  140. base::Unretained(this)));
  141. RunThreads();
  142. EXPECT_EQ(2, post_interceptor_->GetHitCount())
  143. << post_interceptor_->GetRequestsAsString();
  144. EXPECT_EQ(2, post_interceptor_->GetCount())
  145. << post_interceptor_->GetRequestsAsString();
  146. EXPECT_EQ(1, post_interceptor_->GetHitCountForURL(GURL(kUrl1)))
  147. << post_interceptor_->GetRequestsAsString();
  148. EXPECT_EQ(1, post_interceptor_->GetHitCountForURL(GURL(kUrl2)))
  149. << post_interceptor_->GetRequestsAsString();
  150. EXPECT_STREQ("test", post_interceptor_->GetRequestBody(0).c_str());
  151. EXPECT_STREQ("test", post_interceptor_->GetRequestBody(1).c_str());
  152. EXPECT_EQ(0, error_);
  153. }
  154. // Tests that the request fails when both urls have failed.
  155. TEST_F(RequestSenderTest, RequestSendFailed) {
  156. EXPECT_TRUE(post_interceptor_->ExpectRequest(
  157. std::make_unique<PartialMatch>("test"), net::HTTP_FORBIDDEN));
  158. EXPECT_TRUE(post_interceptor_->ExpectRequest(
  159. std::make_unique<PartialMatch>("test"), net::HTTP_FORBIDDEN));
  160. const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
  161. request_sender_ = std::make_unique<RequestSender>(config_);
  162. request_sender_->Send(
  163. urls, {}, "test", false,
  164. base::BindOnce(&RequestSenderTest::RequestSenderComplete,
  165. base::Unretained(this)));
  166. RunThreads();
  167. EXPECT_EQ(2, post_interceptor_->GetHitCount())
  168. << post_interceptor_->GetRequestsAsString();
  169. EXPECT_EQ(2, post_interceptor_->GetCount())
  170. << post_interceptor_->GetRequestsAsString();
  171. EXPECT_EQ(1, post_interceptor_->GetHitCountForURL(GURL(kUrl1)))
  172. << post_interceptor_->GetRequestsAsString();
  173. EXPECT_EQ(1, post_interceptor_->GetHitCountForURL(GURL(kUrl2)))
  174. << post_interceptor_->GetRequestsAsString();
  175. EXPECT_STREQ("test", post_interceptor_->GetRequestBody(0).c_str());
  176. EXPECT_STREQ("test", post_interceptor_->GetRequestBody(1).c_str());
  177. EXPECT_EQ(403, error_);
  178. }
  179. // Tests that the request fails when no urls are provided.
  180. TEST_F(RequestSenderTest, RequestSendFailedNoUrls) {
  181. std::vector<GURL> urls;
  182. request_sender_ = std::make_unique<RequestSender>(config_);
  183. request_sender_->Send(
  184. urls, {}, "test", false,
  185. base::BindOnce(&RequestSenderTest::RequestSenderComplete,
  186. base::Unretained(this)));
  187. RunThreads();
  188. EXPECT_EQ(-10002, error_);
  189. }
  190. // Tests that a CUP request fails if the response is not signed.
  191. TEST_F(RequestSenderTest, RequestSendCupError) {
  192. EXPECT_TRUE(
  193. post_interceptor_->ExpectRequest(std::make_unique<PartialMatch>("test"),
  194. test_file("updatecheck_reply_1.json")));
  195. const std::vector<GURL> urls = {GURL(kUrl1)};
  196. request_sender_ = std::make_unique<RequestSender>(config_);
  197. request_sender_->Send(
  198. urls, {}, "test", true,
  199. base::BindOnce(&RequestSenderTest::RequestSenderComplete,
  200. base::Unretained(this)));
  201. RunThreads();
  202. EXPECT_EQ(1, post_interceptor_->GetHitCount())
  203. << post_interceptor_->GetRequestsAsString();
  204. EXPECT_EQ(1, post_interceptor_->GetCount())
  205. << post_interceptor_->GetRequestsAsString();
  206. EXPECT_STREQ("test", post_interceptor_->GetRequestBody(0).c_str());
  207. EXPECT_EQ(-10000, error_);
  208. EXPECT_TRUE(response_.empty());
  209. }
  210. } // namespace update_client