blob: d96e4da7e7fdd58a150bd3f4d4d5d894a4e0146b [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
sorin9797aba2015-04-17 17:15:03108 config_ = nullptr;
sorin395c2ac2014-09-16 21:31:07109}
110
111void RequestSenderTest::RunThreads() {
112 base::RunLoop runloop;
113 quit_closure_ = runloop.QuitClosure();
114 runloop.Run();
115
116 // Since some tests need to drain currently enqueued tasks such as network
117 // intercepts on the IO thread, run the threads until they are
118 // idle. The component updater service won't loop again until the loop count
119 // is set and the service is started.
Francois Dorayff8a6452017-07-27 17:11:58120 scoped_task_environment_.RunUntilIdle();
sorin395c2ac2014-09-16 21:31:07121}
122
123void RequestSenderTest::Quit() {
124 if (!quit_closure_.is_null())
125 quit_closure_.Run();
126}
127
sorin1bc5eff2016-02-17 18:45:17128void RequestSenderTest::RequestSenderComplete(int error,
sorinfccbf2d2016-04-04 20:34:34129 const std::string& response,
130 int retry_after_sec) {
sorin1bc5eff2016-02-17 18:45:17131 error_ = error;
132 response_ = response;
133
sorin395c2ac2014-09-16 21:31:07134 Quit();
135}
136
137// Tests that when a request to the first url succeeds, the subsequent urls are
138// not tried.
139TEST_F(RequestSenderTest, RequestSendSuccess) {
sorin1bc5eff2016-02-17 18:45:17140 EXPECT_TRUE(post_interceptor_1_->ExpectRequest(
141 new PartialMatch("test"), test_file("updatecheck_reply_1.xml")));
sorin395c2ac2014-09-16 21:31:07142
sorin519656c2017-04-28 22:39:34143 const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
144 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17145 request_sender_->Send(false, "test", urls,
sorin395c2ac2014-09-16 21:31:07146 base::Bind(&RequestSenderTest::RequestSenderComplete,
147 base::Unretained(this)));
148 RunThreads();
149
sorin5cabcf0b2015-06-09 00:54:44150 EXPECT_EQ(1, post_interceptor_1_->GetHitCount())
151 << post_interceptor_1_->GetRequestsAsString();
152 EXPECT_EQ(1, post_interceptor_1_->GetCount())
153 << post_interceptor_1_->GetRequestsAsString();
sorin395c2ac2014-09-16 21:31:07154
sorin30474f02017-04-27 00:45:48155 EXPECT_EQ(0, post_interceptor_2_->GetHitCount())
156 << post_interceptor_2_->GetRequestsAsString();
157 EXPECT_EQ(0, post_interceptor_2_->GetCount())
158 << post_interceptor_2_->GetRequestsAsString();
159
sorin1bc5eff2016-02-17 18:45:17160 // Sanity check the request.
sorin5cabcf0b2015-06-09 00:54:44161 EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
sorin1bc5eff2016-02-17 18:45:17162
163 // Check the response post conditions.
164 EXPECT_EQ(0, error_);
165 EXPECT_TRUE(base::StartsWith(response_,
166 "<?xml version='1.0' encoding='UTF-8'?>",
167 base::CompareCase::SENSITIVE));
sorin519656c2017-04-28 22:39:34168 EXPECT_EQ(505ul, response_.size());
sorin395c2ac2014-09-16 21:31:07169}
170
171// Tests that the request succeeds using the second url after the first url
172// has failed.
173TEST_F(RequestSenderTest, RequestSendSuccessWithFallback) {
sorin5cabcf0b2015-06-09 00:54:44174 EXPECT_TRUE(
175 post_interceptor_1_->ExpectRequest(new PartialMatch("test"), 403));
176 EXPECT_TRUE(post_interceptor_2_->ExpectRequest(new PartialMatch("test")));
sorin395c2ac2014-09-16 21:31:07177
sorin519656c2017-04-28 22:39:34178 const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
179 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17180 request_sender_->Send(false, "test", urls,
sorin395c2ac2014-09-16 21:31:07181 base::Bind(&RequestSenderTest::RequestSenderComplete,
182 base::Unretained(this)));
183 RunThreads();
184
sorin5cabcf0b2015-06-09 00:54:44185 EXPECT_EQ(1, post_interceptor_1_->GetHitCount())
186 << post_interceptor_1_->GetRequestsAsString();
187 EXPECT_EQ(1, post_interceptor_1_->GetCount())
188 << post_interceptor_1_->GetRequestsAsString();
189 EXPECT_EQ(1, post_interceptor_2_->GetHitCount())
190 << post_interceptor_2_->GetRequestsAsString();
191 EXPECT_EQ(1, post_interceptor_2_->GetCount())
192 << post_interceptor_2_->GetRequestsAsString();
sorin395c2ac2014-09-16 21:31:07193
sorin5cabcf0b2015-06-09 00:54:44194 EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
195 EXPECT_STREQ("test", post_interceptor_2_->GetRequests()[0].c_str());
sorin1bc5eff2016-02-17 18:45:17196 EXPECT_EQ(0, error_);
sorin395c2ac2014-09-16 21:31:07197}
198
199// Tests that the request fails when both urls have failed.
200TEST_F(RequestSenderTest, RequestSendFailed) {
sorin5cabcf0b2015-06-09 00:54:44201 EXPECT_TRUE(
202 post_interceptor_1_->ExpectRequest(new PartialMatch("test"), 403));
203 EXPECT_TRUE(
204 post_interceptor_2_->ExpectRequest(new PartialMatch("test"), 403));
sorin395c2ac2014-09-16 21:31:07205
sorin519656c2017-04-28 22:39:34206 const std::vector<GURL> urls = {GURL(kUrl1), GURL(kUrl2)};
207 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17208 request_sender_->Send(false, "test", urls,
sorin395c2ac2014-09-16 21:31:07209 base::Bind(&RequestSenderTest::RequestSenderComplete,
210 base::Unretained(this)));
211 RunThreads();
212
sorin5cabcf0b2015-06-09 00:54:44213 EXPECT_EQ(1, post_interceptor_1_->GetHitCount())
214 << post_interceptor_1_->GetRequestsAsString();
215 EXPECT_EQ(1, post_interceptor_1_->GetCount())
216 << post_interceptor_1_->GetRequestsAsString();
217 EXPECT_EQ(1, post_interceptor_2_->GetHitCount())
218 << post_interceptor_2_->GetRequestsAsString();
219 EXPECT_EQ(1, post_interceptor_2_->GetCount())
220 << post_interceptor_2_->GetRequestsAsString();
sorin395c2ac2014-09-16 21:31:07221
sorin5cabcf0b2015-06-09 00:54:44222 EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
223 EXPECT_STREQ("test", post_interceptor_2_->GetRequests()[0].c_str());
sorin1bc5eff2016-02-17 18:45:17224 EXPECT_EQ(403, error_);
sorin395c2ac2014-09-16 21:31:07225}
226
sorin5cabcf0b2015-06-09 00:54:44227// Tests that the request fails when no urls are provided.
228TEST_F(RequestSenderTest, RequestSendFailedNoUrls) {
229 std::vector<GURL> urls;
sorin519656c2017-04-28 22:39:34230 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17231 request_sender_->Send(false, "test", urls,
sorin5cabcf0b2015-06-09 00:54:44232 base::Bind(&RequestSenderTest::RequestSenderComplete,
233 base::Unretained(this)));
234 RunThreads();
235
sorin1bc5eff2016-02-17 18:45:17236 EXPECT_EQ(-1, error_);
237}
238
239// Tests that a CUP request fails if the response is not signed.
240TEST_F(RequestSenderTest, RequestSendCupError) {
241 EXPECT_TRUE(post_interceptor_1_->ExpectRequest(
242 new PartialMatch("test"), test_file("updatecheck_reply_1.xml")));
243
sorin519656c2017-04-28 22:39:34244 const std::vector<GURL> urls = {GURL(kUrl1)};
245 request_sender_ = base::MakeUnique<RequestSender>(config_);
sorin1bc5eff2016-02-17 18:45:17246 request_sender_->Send(true, "test", urls,
247 base::Bind(&RequestSenderTest::RequestSenderComplete,
248 base::Unretained(this)));
249 RunThreads();
250
251 EXPECT_EQ(1, post_interceptor_1_->GetHitCount())
252 << post_interceptor_1_->GetRequestsAsString();
253 EXPECT_EQ(1, post_interceptor_1_->GetCount())
254 << post_interceptor_1_->GetRequestsAsString();
255
256 EXPECT_STREQ("test", post_interceptor_1_->GetRequests()[0].c_str());
257 EXPECT_EQ(RequestSender::kErrorResponseNotTrusted, error_);
258 EXPECT_TRUE(response_.empty());
sorin5cabcf0b2015-06-09 00:54:44259}
260
sorin52ac0882015-01-24 01:15:00261} // namespace update_client