blob: 67ac7dd28447bc570faed8becb526e544e5a0971 [file] [log] [blame]
sorin395c2ac2014-09-16 21:31:071// 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
dchengd0fc6aa92016-04-22 18:03:125#include "components/update_client/request_sender.h"
6
7#include <memory>
8
sorin5cb1f5492014-09-23 04:07:449#include "base/macros.h"
sorin519656c2017-04-28 22:39:3410#include "base/memory/ptr_util.h"
sorin9797aba2015-04-17 17:15:0311#include "base/memory/ref_counted.h"
davidben74f67442016-10-01 01:45:2212#include "base/path_service.h"
sorin395c2ac2014-09-16 21:31:0713#include "base/run_loop.h"
sorin1bc5eff2016-02-17 18:45:1714#include "base/strings/string_util.h"
Francois Dorayff8a6452017-07-27 17:11:5815#include "base/test/scoped_task_environment.h"
gab7966d312016-05-11 20:35:0116#include "base/threading/thread_task_runner_handle.h"
sorinb120440b2015-04-27 16:34:1517#include "components/update_client/test_configurator.h"
18#include "components/update_client/url_request_post_interceptor.h"
sorin395c2ac2014-09-16 21:31:0719#include "net/url_request/url_fetcher.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
sorin52ac0882015-01-24 01:15:0022namespace update_client {
sorin395c2ac2014-09-16 21:31:0723
24namespace {
25
26const char kUrl1[] = "https://localhost2/path1";
27const char kUrl2[] = "https://localhost2/path2";
28const char kUrlPath1[] = "path1";
29const char kUrlPath2[] = "path2";
30
sorin1bc5eff2016-02-17 18:45:1731// TODO(sorin): refactor as a utility function for unit tests.
32base::FilePath test_file(const char* file) {
33 base::FilePath path;
34 PathService::Get(base::DIR_SOURCE_ROOT, &path);
35 return path.AppendASCII("components")
36 .AppendASCII("test")
37 .AppendASCII("data")
38 .AppendASCII("update_client")
39 .AppendASCII(file);
40}
41
sorin395c2ac2014-09-16 21:31:0742} // namespace
43
44class RequestSenderTest : public testing::Test {
45 public:
46 RequestSenderTest();
dcheng30a1b1542014-10-29 21:27:5047 ~RequestSenderTest() override;
sorin395c2ac2014-09-16 21:31:0748
49 // Overrides from testing::Test.
dcheng30a1b1542014-10-29 21:27:5050 void SetUp() override;
51 void TearDown() override;
sorin395c2ac2014-09-16 21:31:0752
sorinfccbf2d2016-04-04 20:34:3453 void RequestSenderComplete(int error,
54 const std::string& response,
55 int retry_after_sec);
sorin395c2ac2014-09-16 21:31:0756
57 protected:
58 void Quit();
59 void RunThreads();
Francois Dorayff8a6452017-07-27 17:11:5860
61 base::test::ScopedTaskEnvironment scoped_task_environment_;
sorin395c2ac2014-09-16 21:31:0762
sorin9797aba2015-04-17 17:15:0363 scoped_refptr<TestConfigurator> config_;
dchengd0fc6aa92016-04-22 18:03:1264 std::unique_ptr<RequestSender> request_sender_;
65 std::unique_ptr<InterceptorFactory> interceptor_factory_;
sorin395c2ac2014-09-16 21:31:0766
sorin519656c2017-04-28 22:39:3467 // Owned by the factory.
68 URLRequestPostInterceptor* post_interceptor_1_ = nullptr;
69 URLRequestPostInterceptor* post_interceptor_2_ = nullptr;
sorin395c2ac2014-09-16 21:31:0770
sorin519656c2017-04-28 22:39:3471 int error_ = 0;
sorin1bc5eff2016-02-17 18:45:1772 std::string response_;
sorin395c2ac2014-09-16 21:31:0773
74 private:
sorin395c2ac2014-09-16 21:31:0775 base::Closure quit_closure_;
76
77 DISALLOW_COPY_AND_ASSIGN(RequestSenderTest);
78};
79
Francois Dorayff8a6452017-07-27 17:11:5880RequestSenderTest::RequestSenderTest()
81 : scoped_task_environment_(
82 base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
sorin395c2ac2014-09-16 21:31:0783
sorin1bc5eff2016-02-17 18:45:1784RequestSenderTest::~RequestSenderTest() {}
sorin395c2ac2014-09-16 21:31:0785
86void RequestSenderTest::SetUp() {
Sorin Jianucc048f892017-07-26 02:05:5487 config_ = base::MakeRefCounted<TestConfigurator>();
sorin519656c2017-04-28 22:39:3488 interceptor_factory_ =
89 base::MakeUnique<InterceptorFactory>(base::ThreadTaskRunnerHandle::Get());
sorin5cabcf0b2015-06-09 00:54:4490 post_interceptor_1_ =
sorin395c2ac2014-09-16 21:31:0791 interceptor_factory_->CreateInterceptorForPath(kUrlPath1);
sorin5cabcf0b2015-06-09 00:54:4492 post_interceptor_2_ =
sorin395c2ac2014-09-16 21:31:0793 interceptor_factory_->CreateInterceptorForPath(kUrlPath2);
sorin5cabcf0b2015-06-09 00:54:4494 EXPECT_TRUE(post_interceptor_1_);
95 EXPECT_TRUE(post_interceptor_2_);
sorin395c2ac2014-09-16 21:31:0796
sorin519656c2017-04-28 22:39:3497 request_sender_ = nullptr;
sorin395c2ac2014-09-16 21:31:0798}
99
100void RequestSenderTest::TearDown() {
sorin519656c2017-04-28 22:39:34101 request_sender_ = nullptr;
sorin395c2ac2014-09-16 21:31:07102
sorin5cabcf0b2015-06-09 00:54:44103 post_interceptor_1_ = nullptr;
104 post_interceptor_2_ = nullptr;
sorin395c2ac2014-09-16 21:31:07105
sorin519656c2017-04-28 22:39:34106 interceptor_factory_ = nullptr;
sorin395c2ac2014-09-16 21:31:07107
Sorin Jianuf805c222017-09-20 22:36:21108 // Run the threads until they are idle to allow the clean up
109 // of the network interceptors on the IO thread.
110 scoped_task_environment_.RunUntilIdle();
sorin9797aba2015-04-17 17:15:03111 config_ = nullptr;
sorin395c2ac2014-09-16 21:31:07112}
113
114void RequestSenderTest::RunThreads() {
115 base::RunLoop runloop;
116 quit_closure_ = runloop.QuitClosure();
117 runloop.Run();
sorin395c2ac2014-09-16 21:31:07118}
119
120void RequestSenderTest::Quit() {
121 if (!quit_closure_.is_null())
122 quit_closure_.Run();
123}
124
sorin1bc5eff2016-02-17 18:45:17125void RequestSenderTest::RequestSenderComplete(int error,
sorinfccbf2d2016-04-04 20:34:34126 const std::string& response,
127 int retry_after_sec) {
sorin1bc5eff2016-02-17 18:45:17128 error_ = error;
129 response_ = response;
130
sorin395c2ac2014-09-16 21:31:07131 Quit();
132}
133
134// Tests that when a request to the first url succeeds, the subsequent urls are
135// not tried.
136TEST_F(RequestSenderTest, RequestSendSuccess) {
sorin1bc5eff2016-02-17 18:45:17137 EXPECT_TRUE(post_interceptor_1_->ExpectRequest(
138 new PartialMatch("test"), test_file("updatecheck_reply_1.xml")));
sorin395c2ac2014-09-16 21:31:07139
sorin519656c2017-04-28 22:39:34140 const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
141 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17142 request_sender_->Send(false, "test", urls,
sorin395c2ac2014-09-16 21:31:07143 base::Bind(&RequestSenderTest::RequestSenderComplete,
144 base::Unretained(this)));
145 RunThreads();
146
sorin5cabcf0b2015-06-09 00:54:44147 EXPECT_EQ(1, post_interceptor_1_->GetHitCount())
148 << post_interceptor_1_->GetRequestsAsString();
149 EXPECT_EQ(1, post_interceptor_1_->GetCount())
150 << post_interceptor_1_->GetRequestsAsString();
sorin395c2ac2014-09-16 21:31:07151
sorin30474f02017-04-27 00:45:48152 EXPECT_EQ(0, post_interceptor_2_->GetHitCount())
153 << post_interceptor_2_->GetRequestsAsString();
154 EXPECT_EQ(0, post_interceptor_2_->GetCount())
155 << post_interceptor_2_->GetRequestsAsString();
156
sorin1bc5eff2016-02-17 18:45:17157 // Sanity check the request.
sorin5cabcf0b2015-06-09 00:54:44158 EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
sorin1bc5eff2016-02-17 18:45:17159
160 // Check the response post conditions.
161 EXPECT_EQ(0, error_);
162 EXPECT_TRUE(base::StartsWith(response_,
163 "<?xml version='1.0' encoding='UTF-8'?>",
164 base::CompareCase::SENSITIVE));
sorin519656c2017-04-28 22:39:34165 EXPECT_EQ(505ul, response_.size());
Sorin Jianuf805c222017-09-20 22:36:21166
167 interceptor_factory_ = nullptr;
sorin395c2ac2014-09-16 21:31:07168}
169
170// Tests that the request succeeds using the second url after the first url
171// has failed.
172TEST_F(RequestSenderTest, RequestSendSuccessWithFallback) {
sorin5cabcf0b2015-06-09 00:54:44173 EXPECT_TRUE(
174 post_interceptor_1_->ExpectRequest(new PartialMatch("test"), 403));
175 EXPECT_TRUE(post_interceptor_2_->ExpectRequest(new PartialMatch("test")));
sorin395c2ac2014-09-16 21:31:07176
sorin519656c2017-04-28 22:39:34177 const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
178 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17179 request_sender_->Send(false, "test", urls,
sorin395c2ac2014-09-16 21:31:07180 base::Bind(&RequestSenderTest::RequestSenderComplete,
181 base::Unretained(this)));
182 RunThreads();
183
sorin5cabcf0b2015-06-09 00:54:44184 EXPECT_EQ(1, post_interceptor_1_->GetHitCount())
185 << post_interceptor_1_->GetRequestsAsString();
186 EXPECT_EQ(1, post_interceptor_1_->GetCount())
187 << post_interceptor_1_->GetRequestsAsString();
188 EXPECT_EQ(1, post_interceptor_2_->GetHitCount())
189 << post_interceptor_2_->GetRequestsAsString();
190 EXPECT_EQ(1, post_interceptor_2_->GetCount())
191 << post_interceptor_2_->GetRequestsAsString();
sorin395c2ac2014-09-16 21:31:07192
sorin5cabcf0b2015-06-09 00:54:44193 EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
194 EXPECT_STREQ("test", post_interceptor_2_->GetRequests()[0].c_str());
sorin1bc5eff2016-02-17 18:45:17195 EXPECT_EQ(0, error_);
sorin395c2ac2014-09-16 21:31:07196}
197
198// Tests that the request fails when both urls have failed.
199TEST_F(RequestSenderTest, RequestSendFailed) {
sorin5cabcf0b2015-06-09 00:54:44200 EXPECT_TRUE(
201 post_interceptor_1_->ExpectRequest(new PartialMatch("test"), 403));
202 EXPECT_TRUE(
203 post_interceptor_2_->ExpectRequest(new PartialMatch("test"), 403));
sorin395c2ac2014-09-16 21:31:07204
sorin519656c2017-04-28 22:39:34205 const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
206 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17207 request_sender_->Send(false, "test", urls,
sorin395c2ac2014-09-16 21:31:07208 base::Bind(&RequestSenderTest::RequestSenderComplete,
209 base::Unretained(this)));
210 RunThreads();
211
sorin5cabcf0b2015-06-09 00:54:44212 EXPECT_EQ(1, post_interceptor_1_->GetHitCount())
213 << post_interceptor_1_->GetRequestsAsString();
214 EXPECT_EQ(1, post_interceptor_1_->GetCount())
215 << post_interceptor_1_->GetRequestsAsString();
216 EXPECT_EQ(1, post_interceptor_2_->GetHitCount())
217 << post_interceptor_2_->GetRequestsAsString();
218 EXPECT_EQ(1, post_interceptor_2_->GetCount())
219 << post_interceptor_2_->GetRequestsAsString();
sorin395c2ac2014-09-16 21:31:07220
sorin5cabcf0b2015-06-09 00:54:44221 EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
222 EXPECT_STREQ("test", post_interceptor_2_->GetRequests()[0].c_str());
sorin1bc5eff2016-02-17 18:45:17223 EXPECT_EQ(403, error_);
sorin395c2ac2014-09-16 21:31:07224}
225
sorin5cabcf0b2015-06-09 00:54:44226// Tests that the request fails when no urls are provided.
227TEST_F(RequestSenderTest, RequestSendFailedNoUrls) {
228 std::vector<GURL> urls;
sorin519656c2017-04-28 22:39:34229 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17230 request_sender_->Send(false, "test", urls,
sorin5cabcf0b2015-06-09 00:54:44231 base::Bind(&RequestSenderTest::RequestSenderComplete,
232 base::Unretained(this)));
233 RunThreads();
234
sorin1bc5eff2016-02-17 18:45:17235 EXPECT_EQ(-1, error_);
236}
237
238// Tests that a CUP request fails if the response is not signed.
239TEST_F(RequestSenderTest, RequestSendCupError) {
240 EXPECT_TRUE(post_interceptor_1_->ExpectRequest(
241 new PartialMatch("test"), test_file("updatecheck_reply_1.xml")));
242
sorin519656c2017-04-28 22:39:34243 const std::vector<GURL> urls = {GURL(kUrl1)};
244 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17245 request_sender_->Send(true, "test", urls,
246 base::Bind(&RequestSenderTest::RequestSenderComplete,
247 base::Unretained(this)));
248 RunThreads();
249
250 EXPECT_EQ(1, post_interceptor_1_->GetHitCount())
251 << post_interceptor_1_->GetRequestsAsString();
252 EXPECT_EQ(1, post_interceptor_1_->GetCount())
253 << post_interceptor_1_->GetRequestsAsString();
254
255 EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
256 EXPECT_EQ(RequestSender::kErrorResponseNotTrusted, error_);
257 EXPECT_TRUE(response_.empty());
sorin5cabcf0b2015-06-09 00:54:44258}
259
sorin52ac0882015-01-24 01:15:00260} // namespace update_client