blob: 66767fb55931e98eb3022ba5eb94395f7abe91cc [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
rspangler@google.com49fdf182009-10-10 00:57:34 +000016
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070017#include <netinet/in.h>
18#include <netinet/ip.h>
19#include <sys/socket.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +000020#include <unistd.h>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070021
Ben Chan02f7c1d2014-10-18 15:18:02 -070022#include <memory>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000023#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070024#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000025#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070026
Alex Deymo706a5ab2015-11-23 17:48:30 -030027#include <base/bind.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070028#include <base/location.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080029#include <base/logging.h>
Alex Deymo535f3b72015-08-07 10:51:32 -070030#include <base/message_loop/message_loop.h>
31#include <base/strings/string_number_conversions.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070032#include <base/strings/string_util.h>
33#include <base/strings/stringprintf.h>
34#include <base/time/time.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070035#include <brillo/message_loops/base_message_loop.h>
36#include <brillo/message_loops/message_loop.h>
37#include <brillo/message_loops/message_loop_utils.h>
38#include <brillo/process.h>
39#include <brillo/streams/file_stream.h>
40#include <brillo/streams/stream.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080041#include <gtest/gtest.h>
42
Alex Deymoc1c17b42015-11-23 03:53:15 -030043#include "update_engine/common/fake_hardware.h"
Alex Deymo2c131bb2016-05-26 16:43:13 -070044#include "update_engine/common/file_fetcher.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080045#include "update_engine/common/http_common.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080046#include "update_engine/common/mock_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070047#include "update_engine/common/mock_proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080048#include "update_engine/common/multi_range_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070049#include "update_engine/common/proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080050#include "update_engine/common/test_utils.h"
51#include "update_engine/common/utils.h"
Alex Deymo14c0da82016-07-20 16:45:45 -070052#include "update_engine/libcurl_http_fetcher.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000053
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070054using brillo::MessageLoop;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070055using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080056using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000057using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070058using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000059using std::vector;
Alex Deymof2858572016-02-25 11:20:13 -080060using testing::DoAll;
61using testing::Return;
62using testing::SaveArg;
63using testing::_;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000064
Gilad Arnold9bedeb52011-11-17 16:19:57 -080065namespace {
66
67const int kBigLength = 100000;
68const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080069const int kFlakyTruncateLength = 29000;
70const int kFlakySleepEvery = 3;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080071const int kFlakySleepSecs = 10;
72
73} // namespace
74
rspangler@google.com49fdf182009-10-10 00:57:34 +000075namespace chromeos_update_engine {
76
Gilad Arnold9bedeb52011-11-17 16:19:57 -080077static const char *kUnusedUrl = "unused://unused";
78
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070079static inline string LocalServerUrlForPath(in_port_t port,
80 const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070081 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070082 return base::StringPrintf("http://127.0.0.1%s%s", port_str.c_str(),
83 path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000084}
85
Gilad Arnold9bedeb52011-11-17 16:19:57 -080086//
87// Class hierarchy for HTTP server implementations.
88//
89
90class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000091 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080092 // This makes it an abstract class (dirty but works).
93 virtual ~HttpServer() = 0;
94
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070095 virtual in_port_t GetPort() const {
96 return 0;
97 }
98
rspangler@google.com49fdf182009-10-10 00:57:34 +000099 bool started_;
100};
101
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800102HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000103
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800104
105class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000106 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800107 NullHttpServer() {
108 started_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000109 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000110};
111
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800112
113class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000114 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700115 PythonHttpServer() : port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000116 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700117
118 // Spawn the server process.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700119 unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
Sen Jiang260f03b2016-03-21 15:34:58 -0700120 http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
Alex Deymo535f3b72015-08-07 10:51:32 -0700121 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
122
123 if (!http_server->Start()) {
124 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000125 return;
126 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700127 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700128
129 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700130 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700131 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
132 if (!stdout)
133 return;
134
135 vector<char> buf(128);
136 string line;
137 while (line.find('\n') == string::npos) {
138 size_t read;
139 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
140 ADD_FAILURE() << "error reading http server stdout";
141 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700142 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700143 line.append(buf.data(), read);
144 if (read == 0)
145 break;
146 }
147 // Parse the port from the output line.
148 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
149 if (line.size() < listening_msg_prefix_len) {
150 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700151 return;
152 }
153
Alex Deymo535f3b72015-08-07 10:51:32 -0700154 EXPECT_EQ(kServerListeningMsgPrefix,
155 line.substr(0, listening_msg_prefix_len));
156 string port_str = line.substr(listening_msg_prefix_len);
157 port_str.resize(port_str.find('\n'));
158 EXPECT_TRUE(base::StringToUint(port_str, &port_));
159
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700160 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700161 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700162
163 // Any failure before this point will SIGKILL the test server if started
164 // when the |http_server| goes out of scope.
165 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000166 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800167
rspangler@google.com49fdf182009-10-10 00:57:34 +0000168 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700169 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700170 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000171 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700172 // Wait up to 10 seconds for the process to finish. Destroying the process
173 // will kill it with a SIGKILL otherwise.
174 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000175 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800176
Alex Deymo610277e2014-11-11 21:18:11 -0800177 in_port_t GetPort() const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700178 return port_;
179 }
180
181 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700182 static const char* kServerListeningMsgPrefix;
183
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700184 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700185 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000186};
187
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700188const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
189
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800190//
191// Class hierarchy for HTTP fetcher test wrappers.
192//
193
194class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000195 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700196 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700197 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700198
Alex Deymof2858572016-02-25 11:20:13 -0800199 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
200 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
201 proxy_resolver_.set_num_proxies(num_proxies);
202 return NewLargeFetcher(&proxy_resolver_);
203 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800204 HttpFetcher* NewLargeFetcher() {
205 return NewLargeFetcher(1);
206 }
207
Alex Deymof2858572016-02-25 11:20:13 -0800208 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800209 HttpFetcher* NewSmallFetcher() {
Alex Deymof2858572016-02-25 11:20:13 -0800210 proxy_resolver_.set_num_proxies(1);
211 return NewSmallFetcher(&proxy_resolver_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800212 }
213
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700214 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
215 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
216 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800217
218 virtual bool IsMock() const = 0;
219 virtual bool IsMulti() const = 0;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700220 virtual bool IsHttpSupported() const = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800221
222 virtual void IgnoreServerAborting(HttpServer* server) const {}
223
Alex Deymo60ca1a72015-06-18 18:19:15 -0700224 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800225
Alex Deymoc1c17b42015-11-23 03:53:15 -0300226 FakeHardware* fake_hardware() {
Alex Deymo706a5ab2015-11-23 17:48:30 -0300227 return &fake_hardware_;
Alex Deymoc1c17b42015-11-23 03:53:15 -0300228 }
229
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800230 protected:
231 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300232 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800233};
234
235class MockHttpFetcherTest : public AnyHttpFetcherTest {
236 public:
237 // Necessary to unhide the definition in the base class.
238 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800239 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700240 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800241 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800242 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800243 }
244
245 // Necessary to unhide the definition in the base class.
246 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800247 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
248 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800249 }
250
Alex Deymo610277e2014-11-11 21:18:11 -0800251 bool IsMock() const override { return true; }
252 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700253 bool IsHttpSupported() const override { return true; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800254
Alex Deymo60ca1a72015-06-18 18:19:15 -0700255 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800256 return new NullHttpServer;
257 }
258};
259
260class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
261 public:
262 // Necessary to unhide the definition in the base class.
263 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800264 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
265 LibcurlHttpFetcher* ret =
266 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700267 // Speed up test execution.
268 ret->set_idle_seconds(1);
269 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300270 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000271 return ret;
272 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800273
274 // Necessary to unhide the definition in the base class.
275 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800276 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
277 return NewLargeFetcher(proxy_resolver);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000278 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800279
Alex Deymo610277e2014-11-11 21:18:11 -0800280 string BigUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700281 return LocalServerUrlForPath(port,
282 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800283 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000284 }
Alex Deymo610277e2014-11-11 21:18:11 -0800285 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700286 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000287 }
Alex Deymo610277e2014-11-11 21:18:11 -0800288 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700289 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800290 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800291
Alex Deymo610277e2014-11-11 21:18:11 -0800292 bool IsMock() const override { return false; }
293 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700294 bool IsHttpSupported() const override { return true; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800295
Alex Deymo610277e2014-11-11 21:18:11 -0800296 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700297 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700298 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800299
Alex Deymo60ca1a72015-06-18 18:19:15 -0700300 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800301 return new PythonHttpServer;
302 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000303};
304
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800305class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700306 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800307 // Necessary to unhide the definition in the base class.
308 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800309 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
310 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
311 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800312 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800313 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700314 // Speed up test execution.
315 ret->set_idle_seconds(1);
316 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300317 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700318 return ret;
319 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800320
321 // Necessary to unhide the definition in the base class.
322 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800323 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
324 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800325 }
326
Alex Deymo610277e2014-11-11 21:18:11 -0800327 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700328};
329
Alex Deymo2c131bb2016-05-26 16:43:13 -0700330class FileFetcherTest : public AnyHttpFetcherTest {
331 public:
332 // Necessary to unhide the definition in the base class.
333 using AnyHttpFetcherTest::NewLargeFetcher;
334 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
335 return new FileFetcher();
336 }
337
338 // Necessary to unhide the definition in the base class.
339 using AnyHttpFetcherTest::NewSmallFetcher;
340 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
341 return NewLargeFetcher(proxy_resolver);
342 }
343
344 string BigUrl(in_port_t port) const override {
345 return "file://" + temp_file_.path();
346 }
347 string SmallUrl(in_port_t port) const override {
348 test_utils::WriteFileString(temp_file_.path(), "small contents");
349 return "file://" + temp_file_.path();
350 }
351 string ErrorUrl(in_port_t port) const override {
352 return "file:///path/to/non-existing-file";
353 }
354
355 bool IsMock() const override { return false; }
356 bool IsMulti() const override { return false; }
357 bool IsHttpSupported() const override { return false; }
358
359 void IgnoreServerAborting(HttpServer* server) const override {}
360
361 HttpServer* CreateServer() override { return new NullHttpServer; }
362
363 private:
364 test_utils::ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
365};
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800366
367//
368// Infrastructure for type tests of HTTP fetcher.
369// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
370//
371
372// Fixture class template. We use an explicit constraint to guarantee that it
373// can only be instantiated with an AnyHttpFetcherTest type, see:
374// http://www2.research.att.com/~bs/bs_faq2.html#constraints
375template <typename T>
376class HttpFetcherTest : public ::testing::Test {
377 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700378 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700379 brillo::BaseMessageLoop loop_{&base_loop_};
Alex Deymo60ca1a72015-06-18 18:19:15 -0700380
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800381 T test_;
382
Alex Deymo60ca1a72015-06-18 18:19:15 -0700383 protected:
384 HttpFetcherTest() {
385 loop_.SetAsCurrent();
386 }
387
388 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700389 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700390 }
391
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800392 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700393 static void TypeConstraint(T* a) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800394 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700395 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700396 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800397 }
398};
399
400// Test case types list.
401typedef ::testing::Types<LibcurlHttpFetcherTest,
402 MockHttpFetcherTest,
Alex Deymo2c131bb2016-05-26 16:43:13 -0700403 MultiRangeHttpFetcherTest,
404 FileFetcherTest>
405 HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000406TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
407
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800408
rspangler@google.com49fdf182009-10-10 00:57:34 +0000409namespace {
410class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000411 public:
Alex Deymofdd6dec2016-03-03 22:35:43 -0800412 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800413
Amin Hassani0cd9d772018-07-31 23:55:43 -0700414 bool ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymofdd6dec2016-03-03 22:35:43 -0800415 const void* bytes,
416 size_t length) override {
417 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800418 // Update counters
419 times_received_bytes_called_++;
Amin Hassani0cd9d772018-07-31 23:55:43 -0700420 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000421 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800422
Alex Deymo610277e2014-11-11 21:18:11 -0800423 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800424 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800425 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800426 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800427 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700428 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800429
430 // Update counter
431 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000432 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800433
Alex Deymo610277e2014-11-11 21:18:11 -0800434 void TransferTerminated(HttpFetcher* fetcher) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800435 times_transfer_terminated_called_++;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700436 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800437 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800438
Gilad Arnold48085ba2011-11-16 09:36:08 -0800439 // Are we expecting an error response? (default: no)
Alex Deymofdd6dec2016-03-03 22:35:43 -0800440 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800441
442 // Counters for callback invocations.
Alex Deymofdd6dec2016-03-03 22:35:43 -0800443 int times_transfer_complete_called_{0};
444 int times_transfer_terminated_called_{0};
445 int times_received_bytes_called_{0};
446
447 // The received data bytes.
448 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000449};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000450
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000451
Alex Deymo60ca1a72015-06-18 18:19:15 -0700452void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
453 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000454}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700455} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000456
457TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700458 HttpFetcherTestDelegate delegate;
459 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
460 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000461
Alex Deymo60ca1a72015-06-18 18:19:15 -0700462 unique_ptr<HttpServer> server(this->test_.CreateServer());
463 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000464
Alex Deymo60ca1a72015-06-18 18:19:15 -0700465 this->loop_.PostTask(FROM_HERE, base::Bind(
466 StartTransfer,
467 fetcher.get(),
468 this->test_.SmallUrl(server->GetPort())));
469 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800470 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000471}
472
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700473TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700474 HttpFetcherTestDelegate delegate;
475 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
476 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700477
Alex Deymo60ca1a72015-06-18 18:19:15 -0700478 unique_ptr<HttpServer> server(this->test_.CreateServer());
479 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700480
Alex Deymo60ca1a72015-06-18 18:19:15 -0700481 this->loop_.PostTask(FROM_HERE, base::Bind(
482 StartTransfer,
483 fetcher.get(),
484 this->test_.BigUrl(server->GetPort())));
485 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800486 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700487}
488
Gilad Arnold48085ba2011-11-16 09:36:08 -0800489// Issue #9648: when server returns an error HTTP response, the fetcher needs to
490// terminate transfer prematurely, rather than try to process the error payload.
491TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800492 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800493 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700494 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800495
Alex Deymo60ca1a72015-06-18 18:19:15 -0700496 // Delegate should expect an error response.
497 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800498
Alex Deymo60ca1a72015-06-18 18:19:15 -0700499 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
500 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800501
Alex Deymo60ca1a72015-06-18 18:19:15 -0700502 unique_ptr<HttpServer> server(this->test_.CreateServer());
503 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800504
Alex Deymo60ca1a72015-06-18 18:19:15 -0700505 this->loop_.PostTask(FROM_HERE, base::Bind(
506 StartTransfer,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800507 fetcher.get(),
Alex Deymo60ca1a72015-06-18 18:19:15 -0700508 this->test_.ErrorUrl(server->GetPort())));
509 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800510
Alex Deymo60ca1a72015-06-18 18:19:15 -0700511 // Make sure that no bytes were received.
Alex Deymo71f67622017-02-03 21:30:24 -0800512 EXPECT_EQ(0, delegate.times_received_bytes_called_);
513 EXPECT_EQ(0U, fetcher->GetBytesDownloaded());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800514
Alex Deymo60ca1a72015-06-18 18:19:15 -0700515 // Make sure that transfer completion was signaled once, and no termination
516 // was signaled.
Alex Deymo71f67622017-02-03 21:30:24 -0800517 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
518 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800519}
520
Alex Deymofdd6dec2016-03-03 22:35:43 -0800521TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700522 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymofdd6dec2016-03-03 22:35:43 -0800523 return;
524
525 HttpFetcherTestDelegate delegate;
526 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
527 fetcher->set_delegate(&delegate);
528 fetcher->SetHeader("User-Agent", "MyTest");
529 fetcher->SetHeader("user-agent", "Override that header");
530 fetcher->SetHeader("Authorization", "Basic user:passwd");
531
532 // Invalid headers.
533 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
534 fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
535
536 // Hide Accept header normally added by default.
537 fetcher->SetHeader("Accept", "");
538
539 PythonHttpServer server;
540 int port = server.GetPort();
541 ASSERT_TRUE(server.started_);
542
Alex Deymo2c131bb2016-05-26 16:43:13 -0700543 this->loop_.PostTask(
544 FROM_HERE,
545 base::Bind(StartTransfer,
546 fetcher.get(),
547 LocalServerUrlForPath(port, "/echo-headers")));
Alex Deymofdd6dec2016-03-03 22:35:43 -0800548 this->loop_.Run();
549
550 EXPECT_NE(string::npos,
551 delegate.data.find("user-agent: Override that header\r\n"));
552 EXPECT_NE(string::npos,
553 delegate.data.find("Authorization: Basic user:passwd\r\n"));
554
555 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
556 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
557 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
558}
559
rspangler@google.com49fdf182009-10-10 00:57:34 +0000560namespace {
561class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
562 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700563 bool ReceivedBytes(HttpFetcher* fetcher,
564 const void* /* bytes */,
565 size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000566 CHECK(!paused_);
567 paused_ = true;
568 fetcher->Pause();
Amin Hassani0cd9d772018-07-31 23:55:43 -0700569 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000570 }
Alex Deymo610277e2014-11-11 21:18:11 -0800571 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700572 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000573 }
Alex Deymo610277e2014-11-11 21:18:11 -0800574 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800575 ADD_FAILURE();
576 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000577 void Unpause() {
578 CHECK(paused_);
579 paused_ = false;
580 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000581 }
582 bool paused_;
583 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000584};
585
Alex Deymo60ca1a72015-06-18 18:19:15 -0700586void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
587 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000588 if (delegate->paused_)
589 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700590 // Update the task id with the new scheduled callback.
591 *my_id = MessageLoop::current()->PostDelayedTask(
592 FROM_HERE,
593 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
594 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000595}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700596} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000597
598TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800599 PausingHttpFetcherTestDelegate delegate;
600 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
601 delegate.paused_ = false;
602 delegate.fetcher_ = fetcher.get();
603 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000604
Alex Deymof2858572016-02-25 11:20:13 -0800605 unique_ptr<HttpServer> server(this->test_.CreateServer());
606 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800607
Alex Deymof2858572016-02-25 11:20:13 -0800608 MessageLoop::TaskId callback_id;
609 callback_id = this->loop_.PostDelayedTask(
610 FROM_HERE,
611 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
612 base::TimeDelta::FromMilliseconds(200));
613 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000614
Alex Deymof2858572016-02-25 11:20:13 -0800615 this->loop_.Run();
616 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
617}
618
619// This test will pause the fetcher while the download is not yet started
620// because it is waiting for the proxy to be resolved.
621TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700622 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymof2858572016-02-25 11:20:13 -0800623 return;
624 MockProxyResolver mock_resolver;
625 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
626
627 // Saved arguments from the proxy call.
Alex Deymo35821942017-02-05 04:36:02 +0000628 ProxiesResolvedFn proxy_callback;
629 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _))
630 .WillOnce(DoAll(SaveArg<1>(&proxy_callback), Return(true)));
Alex Deymof2858572016-02-25 11:20:13 -0800631 fetcher->BeginTransfer("http://fake_url");
632 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
633
634 // Pausing and unpausing while resolving the proxy should not affect anything.
635 fetcher->Pause();
636 fetcher->Unpause();
637 fetcher->Pause();
638 // Proxy resolver comes back after we paused the fetcher.
Alex Deymoc00ec562017-02-05 04:36:02 +0000639 ASSERT_FALSE(proxy_callback.is_null());
Alex Deymo35821942017-02-05 04:36:02 +0000640 proxy_callback.Run({1, kNoProxy});
rspangler@google.com49fdf182009-10-10 00:57:34 +0000641}
642
643namespace {
644class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
645 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700646 bool ReceivedBytes(HttpFetcher* fetcher,
647 const void* bytes,
648 size_t length) override {
649 return true;
650 }
Alex Deymo610277e2014-11-11 21:18:11 -0800651 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800652 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700653 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000654 }
Alex Deymo610277e2014-11-11 21:18:11 -0800655 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800656 EXPECT_EQ(fetcher, fetcher_.get());
657 EXPECT_FALSE(once_);
658 EXPECT_TRUE(callback_once_);
659 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700660 // The fetcher could have a callback scheduled on the ProxyResolver that
661 // can fire after this callback. We wait until the end of the test to
662 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800663 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000664 void TerminateTransfer() {
665 CHECK(once_);
666 once_ = false;
667 fetcher_->TerminateTransfer();
668 }
669 void EndLoop() {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700670 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000671 }
672 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800673 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700674 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000675};
676
Alex Deymo60ca1a72015-06-18 18:19:15 -0700677void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
678 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000679 if (delegate->once_) {
680 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700681 *my_id = MessageLoop::current()->PostTask(
682 FROM_HERE,
683 base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000684 } else {
685 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700686 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000687 }
688}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700689} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000690
691TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700692 AbortingHttpFetcherTestDelegate delegate;
693 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
694 delegate.once_ = true;
695 delegate.callback_once_ = true;
696 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000697
Alex Deymo60ca1a72015-06-18 18:19:15 -0700698 unique_ptr<HttpServer> server(this->test_.CreateServer());
699 this->test_.IgnoreServerAborting(server.get());
700 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800701
Alex Deymo60ca1a72015-06-18 18:19:15 -0700702 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000703
Alex Deymo60ca1a72015-06-18 18:19:15 -0700704 task_id = this->loop_.PostTask(
705 FROM_HERE,
706 base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
707 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
708
709 this->loop_.Run();
710 CHECK(!delegate.once_);
711 CHECK(!delegate.callback_once_);
712 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000713}
714
Alex Deymo71f67622017-02-03 21:30:24 -0800715TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
716 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
717 return;
718 MockProxyResolver mock_resolver;
719 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
720
721 HttpFetcherTestDelegate delegate;
722 fetcher->set_delegate(&delegate);
723
724 EXPECT_CALL(mock_resolver, GetProxiesForUrl(_, _)).WillOnce(Return(123));
725 fetcher->BeginTransfer("http://fake_url");
726 // Run the message loop until idle. This must call the MockProxyResolver with
727 // the request.
728 while (this->loop_.RunOnce(false)) {
729 }
730 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
731
732 EXPECT_CALL(mock_resolver, CancelProxyRequest(123)).WillOnce(Return(true));
733
734 // Terminate the transfer right before the proxy resolution response.
735 fetcher->TerminateTransfer();
736 EXPECT_EQ(0, delegate.times_received_bytes_called_);
737 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
738 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
739}
740
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000741namespace {
742class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
743 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700744 bool ReceivedBytes(HttpFetcher* fetcher,
745 const void* bytes,
746 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800747 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700748 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000749 }
Alex Deymo610277e2014-11-11 21:18:11 -0800750 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700751 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800752 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700753 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000754 }
Alex Deymo610277e2014-11-11 21:18:11 -0800755 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800756 ADD_FAILURE();
757 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000758 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000759};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700760} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000761
762TYPED_TEST(HttpFetcherTest, FlakyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700763 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000764 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000765 {
766 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700767 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000768 fetcher->set_delegate(&delegate);
769
Ben Chan02f7c1d2014-10-18 15:18:02 -0700770 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800771 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000772
Alex Deymo60ca1a72015-06-18 18:19:15 -0700773 this->loop_.PostTask(FROM_HERE, base::Bind(
774 &StartTransfer,
775 fetcher.get(),
776 LocalServerUrlForPath(server->GetPort(),
777 base::StringPrintf("/flaky/%d/%d/%d/%d",
778 kBigLength,
779 kFlakyTruncateLength,
780 kFlakySleepEvery,
781 kFlakySleepSecs))));
782 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000783
784 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800785 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800786 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000787 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
788 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
789 }
790 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000791}
792
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700793namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700794// This delegate kills the server attached to it after receiving any bytes.
795// This can be used for testing what happens when you try to fetch data and
796// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700797class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
798 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700799 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700800 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700801
Alex Deymo610277e2014-11-11 21:18:11 -0800802 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700803 if (server_) {
804 LOG(INFO) << "Stopping server in destructor";
Alex Deymob20de692017-02-05 07:47:37 +0000805 server_.reset();
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700806 LOG(INFO) << "server stopped";
807 }
808 }
809
Amin Hassani0cd9d772018-07-31 23:55:43 -0700810 bool ReceivedBytes(HttpFetcher* fetcher,
811 const void* bytes,
812 size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700813 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700814 LOG(INFO) << "Stopping server in ReceivedBytes";
Alex Deymob20de692017-02-05 07:47:37 +0000815 server_.reset();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700816 LOG(INFO) << "server stopped";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700817 }
Amin Hassani0cd9d772018-07-31 23:55:43 -0700818 return true;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700819 }
Alex Deymo610277e2014-11-11 21:18:11 -0800820 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700821 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700822 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymob20de692017-02-05 07:47:37 +0000823 times_transfer_complete_called_++;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700824 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700825 }
Alex Deymo610277e2014-11-11 21:18:11 -0800826 void TransferTerminated(HttpFetcher* fetcher) override {
Alex Deymob20de692017-02-05 07:47:37 +0000827 times_transfer_terminated_called_++;
828 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800829 }
Alex Deymob20de692017-02-05 07:47:37 +0000830 unique_ptr<PythonHttpServer> server_;
831 int times_transfer_terminated_called_{0};
832 int times_transfer_complete_called_{0};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700833};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700834} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700835
836
837TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700838 // This test ensures that a fetcher responds correctly when a server isn't
839 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800840 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700841 return;
Alex Deymob20de692017-02-05 07:47:37 +0000842 FailureHttpFetcherTestDelegate delegate(nullptr);
843 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
844 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700845
Alex Deymob20de692017-02-05 07:47:37 +0000846 this->loop_.PostTask(
847 FROM_HERE,
848 base::Bind(
849 StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
850 this->loop_.Run();
851 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
852 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700853
Alex Deymob20de692017-02-05 07:47:37 +0000854 // Exiting and testing happens in the delegate
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700855}
856
Alex Deymof123ae22015-09-24 14:59:43 -0700857TYPED_TEST(HttpFetcherTest, NoResponseTest) {
858 // This test starts a new http server but the server doesn't respond and just
859 // closes the connection.
860 if (this->test_.IsMock())
861 return;
862
863 PythonHttpServer* server = new PythonHttpServer();
864 int port = server->GetPort();
865 ASSERT_TRUE(server->started_);
866
867 // Handles destruction and claims ownership.
868 FailureHttpFetcherTestDelegate delegate(server);
869 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
870 fetcher->set_delegate(&delegate);
871 // The server will not reply at all, so we can limit the execution time of the
872 // test by reducing the low-speed timeout to something small. The test will
873 // finish once the TimeoutCallback() triggers (every second) and the timeout
874 // expired.
875 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
876
877 this->loop_.PostTask(FROM_HERE, base::Bind(
878 StartTransfer,
879 fetcher.get(),
880 LocalServerUrlForPath(port, "/hang")));
881 this->loop_.Run();
Alex Deymob20de692017-02-05 07:47:37 +0000882 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
883 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Alex Deymof123ae22015-09-24 14:59:43 -0700884
885 // Check that no other callback runs in the next two seconds. That would
886 // indicate a leaked callback.
887 bool timeout = false;
Luis Hector Chavezf1cf3482016-07-19 14:29:19 -0700888 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
889 base::Unretained(&timeout));
Alex Deymof123ae22015-09-24 14:59:43 -0700890 this->loop_.PostDelayedTask(FROM_HERE, callback,
891 base::TimeDelta::FromSeconds(2));
892 EXPECT_TRUE(this->loop_.RunOnce(true));
893 EXPECT_TRUE(timeout);
894}
895
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700896TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700897 // This test starts a new http server and kills it after receiving its first
898 // set of bytes. It test whether or not our fetcher eventually gives up on
899 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800900 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700901 return;
Alex Deymob20de692017-02-05 07:47:37 +0000902 PythonHttpServer* server = new PythonHttpServer();
903 int port = server->GetPort();
904 ASSERT_TRUE(server->started_);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700905
Alex Deymob20de692017-02-05 07:47:37 +0000906 // Handles destruction and claims ownership.
907 FailureHttpFetcherTestDelegate delegate(server);
908 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
909 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700910
Alex Deymob20de692017-02-05 07:47:37 +0000911 this->loop_.PostTask(
912 FROM_HERE,
913 base::Bind(StartTransfer,
914 fetcher.get(),
915 LocalServerUrlForPath(port,
916 base::StringPrintf("/flaky/%d/%d/%d/%d",
917 kBigLength,
918 kFlakyTruncateLength,
919 kFlakySleepEvery,
920 kFlakySleepSecs))));
921 this->loop_.Run();
922 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
923 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700924
Alex Deymob20de692017-02-05 07:47:37 +0000925 // Exiting and testing happens in the delegate
926}
927
928// Test that we can cancel a transfer while it is still trying to connect to the
929// server. This test kills the server after a few bytes are received.
930TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
931 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
932 return;
933
934 PythonHttpServer* server = new PythonHttpServer();
935 int port = server->GetPort();
936 ASSERT_TRUE(server->started_);
937
938 // Handles destruction and claims ownership.
939 FailureHttpFetcherTestDelegate delegate(server);
940 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
941 fetcher->set_delegate(&delegate);
942
943 this->loop_.PostTask(
944 FROM_HERE,
945 base::Bind(StartTransfer,
946 fetcher.get(),
947 LocalServerUrlForPath(port,
948 base::StringPrintf("/flaky/%d/%d/%d/%d",
949 kBigLength,
950 kFlakyTruncateLength,
951 kFlakySleepEvery,
952 kFlakySleepSecs))));
953 // Terminating the transfer after 3 seconds gives it a chance to contact the
954 // server and enter the retry loop.
955 this->loop_.PostDelayedTask(FROM_HERE,
956 base::Bind(&HttpFetcher::TerminateTransfer,
957 base::Unretained(fetcher.get())),
958 base::TimeDelta::FromSeconds(3));
959
960 // Exiting and testing happens in the delegate.
961 this->loop_.Run();
962 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
963 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
964
965 // Check that no other callback runs in the next two seconds. That would
966 // indicate a leaked callback.
967 bool timeout = false;
968 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
969 base::Unretained(&timeout));
970 this->loop_.PostDelayedTask(
971 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
972 EXPECT_TRUE(this->loop_.RunOnce(true));
973 EXPECT_TRUE(timeout);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700974}
975
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700976namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800977const HttpResponseCode kRedirectCodes[] = {
978 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
979 kHttpResponseTempRedirect
980};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700981
982class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
983 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700984 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700985 : expected_successful_(expected_successful) {}
Amin Hassani0cd9d772018-07-31 23:55:43 -0700986 bool ReceivedBytes(HttpFetcher* fetcher,
987 const void* bytes,
988 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800989 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700990 return true;
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700991 }
Alex Deymo610277e2014-11-11 21:18:11 -0800992 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700993 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700994 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800995 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700996 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800997 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
998 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700999 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001000 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001001 }
Alex Deymo610277e2014-11-11 21:18:11 -08001002 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001003 ADD_FAILURE();
1004 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001005 bool expected_successful_;
1006 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001007};
1008
1009// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001010void RedirectTest(const HttpServer* server,
1011 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001012 const string& url,
1013 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001014 RedirectHttpFetcherTestDelegate delegate(expected_successful);
1015 unique_ptr<HttpFetcher> fetcher(http_fetcher);
1016 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001017
Alex Deymo60ca1a72015-06-18 18:19:15 -07001018 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1019 StartTransfer,
1020 fetcher.get(),
1021 LocalServerUrlForPath(server->GetPort(), url)));
1022 MessageLoop::current()->Run();
1023 if (expected_successful) {
1024 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -08001025 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -07001026 for (int i = 0; i < kMediumLength; i += 10) {
1027 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
1028 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001029 }
1030 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001031}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001032} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001033
1034TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001035 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001036 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001037
Ben Chan02f7c1d2014-10-18 15:18:02 -07001038 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001039 ASSERT_TRUE(server->started_);
1040
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001041 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001042 const string url = base::StringPrintf("/redirect/%d/download/%d",
1043 kRedirectCodes[c],
1044 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001045 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001046 }
1047}
1048
1049TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001050 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001051 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001052
Ben Chan02f7c1d2014-10-18 15:18:02 -07001053 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001054 ASSERT_TRUE(server->started_);
1055
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001056 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001057 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001058 url += base::StringPrintf("/redirect/%d",
1059 kRedirectCodes[r % arraysize(kRedirectCodes)]);
1060 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001061 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001062 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001063}
1064
1065TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001066 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001067 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001068
Ben Chan02f7c1d2014-10-18 15:18:02 -07001069 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001070 ASSERT_TRUE(server->started_);
1071
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001072 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001073 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001074 url += base::StringPrintf("/redirect/%d",
1075 kRedirectCodes[r % arraysize(kRedirectCodes)]);
1076 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001077 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001078 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001079}
1080
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001081namespace {
1082class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1083 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001084 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001085 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001086
Amin Hassani0cd9d772018-07-31 23:55:43 -07001087 bool ReceivedBytes(HttpFetcher* fetcher,
1088 const void* bytes,
1089 size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001090 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001091 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001092 return true;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001093 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001094
Alex Deymo610277e2014-11-11 21:18:11 -08001095 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001096 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001097 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001098 if (expected_response_code_ != 0)
1099 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001100 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -07001101 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001102 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001103 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001104
Alex Deymo610277e2014-11-11 21:18:11 -08001105 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001106 ADD_FAILURE();
1107 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001108
Ben Chan02f7c1d2014-10-18 15:18:02 -07001109 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001110 int expected_response_code_;
1111 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001112};
1113
1114void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -03001115 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001116 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -07001117 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001118 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -08001119 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001120 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001121 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1122 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001123
Alex Deymo60ca1a72015-06-18 18:19:15 -07001124 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -08001125 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001126 ASSERT_TRUE(multi_fetcher);
1127 multi_fetcher->ClearRanges();
1128 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
1129 e = ranges.end(); it != e; ++it) {
1130 string tmp_str = base::StringPrintf("%jd+", it->first);
1131 if (it->second > 0) {
1132 base::StringAppendF(&tmp_str, "%jd", it->second);
1133 multi_fetcher->AddRange(it->first, it->second);
1134 } else {
1135 base::StringAppendF(&tmp_str, "?");
1136 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001137 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001138 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001139 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001140 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001141 multi_fetcher->set_delegate(&delegate);
1142
1143 MessageLoop::current()->PostTask(
1144 FROM_HERE,
1145 base::Bind(StartTransfer, multi_fetcher, url));
1146 MessageLoop::current()->Run();
1147
1148 EXPECT_EQ(expected_size, delegate.data.size());
1149 EXPECT_EQ(expected_prefix,
1150 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001151}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001152} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001153
Darin Petkov9ce452b2010-11-17 14:33:28 -08001154TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001155 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001156 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001157
Ben Chan02f7c1d2014-10-18 15:18:02 -07001158 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001159 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001160
Ben Chanf9cb98c2014-09-21 18:31:30 -07001161 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001162 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001163 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001164 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001165 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001166 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001167 ranges,
1168 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001169 kBigLength - (99 - 25),
1170 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001171}
1172
1173TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001174 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001175 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001176
Ben Chan02f7c1d2014-10-18 15:18:02 -07001177 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001178 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001179
Ben Chanf9cb98c2014-09-21 18:31:30 -07001180 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001181 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001182 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001183 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001184 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001185 ranges,
1186 "abcdefghijabcdefghijabcd",
1187 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001188 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001189}
1190
1191TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001192 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001193 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001194
Ben Chan02f7c1d2014-10-18 15:18:02 -07001195 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001196 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001197
Ben Chanf9cb98c2014-09-21 18:31:30 -07001198 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001199 ranges.push_back(make_pair(kBigLength - 2, 0));
1200 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001201 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001202 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001203 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001204 ranges,
1205 "ijhij",
1206 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001207 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001208}
1209
1210TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001211 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001212 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001213
Ben Chan02f7c1d2014-10-18 15:18:02 -07001214 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001215 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001216
Ben Chanf9cb98c2014-09-21 18:31:30 -07001217 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001218 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001219 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001220 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001221 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001222 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001223 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001224 ranges,
1225 "ij",
1226 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001227 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001228 ranges.push_back(make_pair(0, 5));
1229 }
1230}
1231
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001232// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1233// should retry with other proxies listed before giving up.
1234//
1235// (1) successful recovery: The offset fetch will fail twice but succeed with
1236// the third proxy.
1237TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1238 if (!this->test_.IsMulti())
1239 return;
1240
Ben Chan02f7c1d2014-10-18 15:18:02 -07001241 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001242 ASSERT_TRUE(server->started_);
1243
Ben Chanf9cb98c2014-09-21 18:31:30 -07001244 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001245 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001246 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001247 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001248 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001249 LocalServerUrlForPath(server->GetPort(),
1250 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001251 kBigLength)),
1252 ranges,
1253 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1254 kBigLength - (99 - 25),
1255 kHttpResponsePartialContent);
1256}
1257
1258// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1259// fetcher will signal a (failed) completed transfer to the delegate.
1260TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1261 if (!this->test_.IsMulti())
1262 return;
1263
Ben Chan02f7c1d2014-10-18 15:18:02 -07001264 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001265 ASSERT_TRUE(server->started_);
1266
Ben Chanf9cb98c2014-09-21 18:31:30 -07001267 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001268 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001269 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001270 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001271 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001272 LocalServerUrlForPath(server->GetPort(),
1273 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001274 kBigLength)),
1275 ranges,
1276 "abcdefghijabcdefghijabcde", // only received the first chunk
1277 25,
1278 kHttpResponseUndefined);
1279}
1280
Alex Deymo4ea2d922017-02-05 07:35:32 +00001281namespace {
1282// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1283class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1284 public:
1285 explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1286 : terminate_trigger_bytes_(terminate_trigger_bytes) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001287
Amin Hassani0cd9d772018-07-31 23:55:43 -07001288 bool ReceivedBytes(HttpFetcher* fetcher,
Alex Deymo4ea2d922017-02-05 07:35:32 +00001289 const void* bytes,
1290 size_t length) override {
1291 LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
1292 EXPECT_EQ(fetcher, fetcher_.get());
1293 if (bytes_downloaded_ < terminate_trigger_bytes_ &&
1294 bytes_downloaded_ + length >= terminate_trigger_bytes_) {
1295 MessageLoop::current()->PostTask(
1296 FROM_HERE,
1297 base::Bind(&HttpFetcher::TerminateTransfer,
1298 base::Unretained(fetcher_.get())));
1299 }
1300 bytes_downloaded_ += length;
Amin Hassani0cd9d772018-07-31 23:55:43 -07001301 return true;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001302 }
1303
1304 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1305 ADD_FAILURE() << "TransferComplete called but expected a failure";
1306 // Destroy the fetcher (because we're allowed to).
1307 fetcher_.reset(nullptr);
1308 MessageLoop::current()->BreakLoop();
1309 }
1310
1311 void TransferTerminated(HttpFetcher* fetcher) override {
1312 // Destroy the fetcher (because we're allowed to).
1313 fetcher_.reset(nullptr);
1314 MessageLoop::current()->BreakLoop();
1315 }
1316
1317 unique_ptr<HttpFetcher> fetcher_;
1318 size_t bytes_downloaded_{0};
1319 size_t terminate_trigger_bytes_;
1320};
1321} // namespace
1322
1323TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
1324 if (!this->test_.IsMulti())
1325 return;
1326 const size_t kRangeTrigger = 1000;
1327 MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
1328
1329 unique_ptr<HttpServer> server(this->test_.CreateServer());
1330 ASSERT_TRUE(server->started_);
1331
1332 MultiRangeHttpFetcher* multi_fetcher =
1333 static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
1334 ASSERT_TRUE(multi_fetcher);
1335 // Transfer ownership of the fetcher to the delegate.
1336 delegate.fetcher_.reset(multi_fetcher);
1337 multi_fetcher->set_delegate(&delegate);
1338
1339 multi_fetcher->ClearRanges();
1340 multi_fetcher->AddRange(45, kRangeTrigger);
1341 multi_fetcher->AddRange(2000, 100);
1342
1343 this->test_.fake_hardware()->SetIsOfficialBuild(false);
1344
1345 StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
1346 MessageLoop::current()->Run();
1347
1348 // Check that the delegate made it to the trigger point.
1349 EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
1350}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001351
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001352namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001353class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001354 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -07001355 bool ReceivedBytes(HttpFetcher* fetcher,
1356 const void* bytes,
1357 size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001358 ADD_FAILURE();
Amin Hassani0cd9d772018-07-31 23:55:43 -07001359 return true;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001360 }
Alex Deymo610277e2014-11-11 21:18:11 -08001361 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001362 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001363 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001364 }
Alex Deymo610277e2014-11-11 21:18:11 -08001365 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001366 ADD_FAILURE();
1367 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001368};
1369
Alex Deymo60ca1a72015-06-18 18:19:15 -07001370void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1371 bool is_official_build) {
1372 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1373 return;
1374
1375 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1376 ASSERT_TRUE(server->started_);
1377
1378 BlockedTransferTestDelegate delegate;
1379 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1380 LOG(INFO) << "is_official_build: " << is_official_build;
1381 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001382 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001383 fetcher->set_delegate(&delegate);
1384
1385 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1386 StartTransfer,
1387 fetcher.get(),
1388 LocalServerUrlForPath(server->GetPort(),
1389 fetcher_test->SmallUrl(server->GetPort()))));
1390 MessageLoop::current()->Run();
1391}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001392} // namespace
1393
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001394TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001395 BlockedTransferTestHelper(&this->test_, false);
1396}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001397
Alex Deymo60ca1a72015-06-18 18:19:15 -07001398TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1399 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001400}
1401
rspangler@google.com49fdf182009-10-10 00:57:34 +00001402} // namespace chromeos_update_engine