blob: bc8a3257175412f6a89278725bc6a287f85f62a3 [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
Tao Bao642b32b2019-01-02 15:33:42 -080022#include <algorithm>
Ben Chan02f7c1d2014-10-18 15:18:02 -070023#include <memory>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000024#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070025#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000026#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070027
Alex Deymo706a5ab2015-11-23 17:48:30 -030028#include <base/bind.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070029#include <base/location.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080030#include <base/logging.h>
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090031#if BASE_VER < 780000 // Android
Alex Deymo535f3b72015-08-07 10:51:32 -070032#include <base/message_loop/message_loop.h>
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090033#endif // BASE_VER < 780000
hscham00b6aa22020-02-20 12:32:06 +090034#include <base/stl_util.h>
Alex Deymo535f3b72015-08-07 10:51:32 -070035#include <base/strings/string_number_conversions.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070036#include <base/strings/string_util.h>
37#include <base/strings/stringprintf.h>
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090038#if BASE_VER >= 780000 // CrOS
39#include <base/task/single_thread_task_executor.h>
40#endif // BASE_VER >= 780000
Alex Vakulenko75039d72014-03-25 12:36:28 -070041#include <base/time/time.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070042#include <brillo/message_loops/base_message_loop.h>
43#include <brillo/message_loops/message_loop.h>
44#include <brillo/message_loops/message_loop_utils.h>
Amin Hassani4bd46b32020-09-15 15:30:09 -070045#ifdef __CHROMEOS__
46#include <brillo/process/process.h>
47#else
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070048#include <brillo/process.h>
Amin Hassani4bd46b32020-09-15 15:30:09 -070049#endif // __CHROMEOS__
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070050#include <brillo/streams/file_stream.h>
51#include <brillo/streams/stream.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080052#include <gtest/gtest.h>
53
Alex Deymoc1c17b42015-11-23 03:53:15 -030054#include "update_engine/common/fake_hardware.h"
Alex Deymo2c131bb2016-05-26 16:43:13 -070055#include "update_engine/common/file_fetcher.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080056#include "update_engine/common/http_common.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080057#include "update_engine/common/mock_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070058#include "update_engine/common/mock_proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080059#include "update_engine/common/multi_range_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070060#include "update_engine/common/proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080061#include "update_engine/common/test_utils.h"
62#include "update_engine/common/utils.h"
Alex Deymo14c0da82016-07-20 16:45:45 -070063#include "update_engine/libcurl_http_fetcher.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000064
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070065using brillo::MessageLoop;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070066using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080067using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000068using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070069using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000070using std::vector;
Amin Hassanib2689592019-01-13 17:04:28 -080071using testing::_;
Alex Deymof2858572016-02-25 11:20:13 -080072using testing::DoAll;
73using testing::Return;
74using testing::SaveArg;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000075
Gilad Arnold9bedeb52011-11-17 16:19:57 -080076namespace {
77
Amin Hassanib2689592019-01-13 17:04:28 -080078const int kBigLength = 100000;
79const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080080const int kFlakyTruncateLength = 29000;
Amin Hassanib2689592019-01-13 17:04:28 -080081const int kFlakySleepEvery = 3;
82const int kFlakySleepSecs = 10;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080083
84} // namespace
85
rspangler@google.com49fdf182009-10-10 00:57:34 +000086namespace chromeos_update_engine {
87
Amin Hassanib2689592019-01-13 17:04:28 -080088static const char* kUnusedUrl = "unused://unused";
Gilad Arnold9bedeb52011-11-17 16:19:57 -080089
Amin Hassanib2689592019-01-13 17:04:28 -080090static inline string LocalServerUrlForPath(in_port_t port, const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070091 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Amin Hassanib2689592019-01-13 17:04:28 -080092 return base::StringPrintf(
93 "http://127.0.0.1%s%s", port_str.c_str(), path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000094}
95
Gilad Arnold9bedeb52011-11-17 16:19:57 -080096//
97// Class hierarchy for HTTP server implementations.
98//
99
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700100namespace {
101
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800102class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000103 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800104 // This makes it an abstract class (dirty but works).
105 virtual ~HttpServer() = 0;
106
Amin Hassanib2689592019-01-13 17:04:28 -0800107 virtual in_port_t GetPort() const { return 0; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700108
rspangler@google.com49fdf182009-10-10 00:57:34 +0000109 bool started_;
110};
111
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800112HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000113
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800114class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000115 public:
Amin Hassanib2689592019-01-13 17:04:28 -0800116 NullHttpServer() { started_ = true; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000117};
118
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800119class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000120 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700121 PythonHttpServer() : port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000122 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700123
124 // Spawn the server process.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700125 unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
Sen Jiang260f03b2016-03-21 15:34:58 -0700126 http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
Alex Deymo535f3b72015-08-07 10:51:32 -0700127 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
128
129 if (!http_server->Start()) {
130 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000131 return;
132 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700133 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700134
135 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700136 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700137 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
138 if (!stdout)
139 return;
140
141 vector<char> buf(128);
142 string line;
143 while (line.find('\n') == string::npos) {
144 size_t read;
145 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
146 ADD_FAILURE() << "error reading http server stdout";
147 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700148 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700149 line.append(buf.data(), read);
150 if (read == 0)
151 break;
152 }
153 // Parse the port from the output line.
154 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
155 if (line.size() < listening_msg_prefix_len) {
156 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700157 return;
158 }
159
Alex Deymo535f3b72015-08-07 10:51:32 -0700160 EXPECT_EQ(kServerListeningMsgPrefix,
161 line.substr(0, listening_msg_prefix_len));
162 string port_str = line.substr(listening_msg_prefix_len);
163 port_str.resize(port_str.find('\n'));
164 EXPECT_TRUE(base::StringToUint(port_str, &port_));
165
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700166 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700167 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700168
169 // Any failure before this point will SIGKILL the test server if started
170 // when the |http_server| goes out of scope.
171 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000172 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800173
rspangler@google.com49fdf182009-10-10 00:57:34 +0000174 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700175 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700176 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000177 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700178 // Wait up to 10 seconds for the process to finish. Destroying the process
179 // will kill it with a SIGKILL otherwise.
180 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000181 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800182
Amin Hassanib2689592019-01-13 17:04:28 -0800183 in_port_t GetPort() const override { return port_; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700184
185 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700186 static const char* kServerListeningMsgPrefix;
187
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700188 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700189 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000190};
191
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700192const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
193
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800194//
195// Class hierarchy for HTTP fetcher test wrappers.
196//
197
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700198class AnyHttpFetcherFactory {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000199 public:
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700200 AnyHttpFetcherFactory() {}
201 virtual ~AnyHttpFetcherFactory() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700202
Alex Deymof2858572016-02-25 11:20:13 -0800203 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
204 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
205 proxy_resolver_.set_num_proxies(num_proxies);
206 return NewLargeFetcher(&proxy_resolver_);
207 }
Amin Hassanib2689592019-01-13 17:04:28 -0800208 HttpFetcher* NewLargeFetcher() { return NewLargeFetcher(1); }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800209
Alex Deymof2858572016-02-25 11:20:13 -0800210 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800211 HttpFetcher* NewSmallFetcher() {
Alex Deymof2858572016-02-25 11:20:13 -0800212 proxy_resolver_.set_num_proxies(1);
213 return NewSmallFetcher(&proxy_resolver_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800214 }
215
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700216 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
217 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
218 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800219
220 virtual bool IsMock() const = 0;
221 virtual bool IsMulti() const = 0;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700222 virtual bool IsHttpSupported() const = 0;
Tao Bao642b32b2019-01-02 15:33:42 -0800223 virtual bool IsFileFetcher() const = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800224
225 virtual void IgnoreServerAborting(HttpServer* server) const {}
226
Alex Deymo60ca1a72015-06-18 18:19:15 -0700227 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800228
Amin Hassanib2689592019-01-13 17:04:28 -0800229 FakeHardware* fake_hardware() { return &fake_hardware_; }
Alex Deymoc1c17b42015-11-23 03:53:15 -0300230
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800231 protected:
232 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300233 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800234};
235
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700236class MockHttpFetcherFactory : public AnyHttpFetcherFactory {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800237 public:
238 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700239 using AnyHttpFetcherFactory::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800240 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700241 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800242 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800243 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800244 }
245
246 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700247 using AnyHttpFetcherFactory::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800248 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
249 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800250 }
251
Alex Deymo610277e2014-11-11 21:18:11 -0800252 bool IsMock() const override { return true; }
253 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700254 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800255 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800256
Amin Hassanib2689592019-01-13 17:04:28 -0800257 HttpServer* CreateServer() override { return new NullHttpServer; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800258};
259
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700260class LibcurlHttpFetcherFactory : public AnyHttpFetcherFactory {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800261 public:
262 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700263 using AnyHttpFetcherFactory::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.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700275 using AnyHttpFetcherFactory::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 {
Amin Hassanib2689592019-01-13 17:04:28 -0800281 return LocalServerUrlForPath(
282 port, base::StringPrintf("/download/%d", kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000283 }
Alex Deymo610277e2014-11-11 21:18:11 -0800284 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700285 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000286 }
Alex Deymo610277e2014-11-11 21:18:11 -0800287 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700288 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800289 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800290
Alex Deymo610277e2014-11-11 21:18:11 -0800291 bool IsMock() const override { return false; }
292 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700293 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800294 bool IsFileFetcher() const override { return false; }
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
Amin Hassanib2689592019-01-13 17:04:28 -0800300 HttpServer* CreateServer() override { return new PythonHttpServer; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000301};
302
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700303class MultiRangeHttpFetcherFactory : public LibcurlHttpFetcherFactory {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700304 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800305 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700306 using AnyHttpFetcherFactory::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800307 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
308 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
309 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800310 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800311 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700312 // Speed up test execution.
313 ret->set_idle_seconds(1);
314 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300315 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700316 return ret;
317 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800318
319 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700320 using AnyHttpFetcherFactory::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800321 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
322 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800323 }
324
Alex Deymo610277e2014-11-11 21:18:11 -0800325 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700326};
327
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700328class FileFetcherFactory : public AnyHttpFetcherFactory {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700329 public:
330 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700331 using AnyHttpFetcherFactory::NewLargeFetcher;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700332 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
333 return new FileFetcher();
334 }
335
336 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700337 using AnyHttpFetcherFactory::NewSmallFetcher;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700338 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
339 return NewLargeFetcher(proxy_resolver);
340 }
341
342 string BigUrl(in_port_t port) const override {
Tao Bao642b32b2019-01-02 15:33:42 -0800343 static string big_contents = []() {
344 string buf;
345 buf.reserve(kBigLength);
346 constexpr const char* kBigUrlContent = "abcdefghij";
347 for (size_t i = 0; i < kBigLength; i += strlen(kBigUrlContent)) {
348 buf.append(kBigUrlContent,
349 std::min(kBigLength - i, strlen(kBigUrlContent)));
350 }
351 return buf;
352 }();
353 test_utils::WriteFileString(temp_file_.path(), big_contents);
Alex Deymo2c131bb2016-05-26 16:43:13 -0700354 return "file://" + temp_file_.path();
355 }
356 string SmallUrl(in_port_t port) const override {
357 test_utils::WriteFileString(temp_file_.path(), "small contents");
358 return "file://" + temp_file_.path();
359 }
360 string ErrorUrl(in_port_t port) const override {
361 return "file:///path/to/non-existing-file";
362 }
363
364 bool IsMock() const override { return false; }
365 bool IsMulti() const override { return false; }
366 bool IsHttpSupported() const override { return false; }
Tao Bao642b32b2019-01-02 15:33:42 -0800367 bool IsFileFetcher() const override { return true; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700368
369 void IgnoreServerAborting(HttpServer* server) const override {}
370
371 HttpServer* CreateServer() override { return new NullHttpServer; }
372
373 private:
Amin Hassanied03b442020-10-26 17:21:29 -0700374 ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
Alex Deymo2c131bb2016-05-26 16:43:13 -0700375};
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800376
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700377class MultiRangeHttpFetcherOverFileFetcherFactory : public FileFetcherFactory {
Tao Bao642b32b2019-01-02 15:33:42 -0800378 public:
379 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700380 using AnyHttpFetcherFactory::NewLargeFetcher;
Tao Bao642b32b2019-01-02 15:33:42 -0800381 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
382 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(new FileFetcher());
383 ret->ClearRanges();
384 // FileFetcher doesn't support range with unspecified length.
385 ret->AddRange(0, 1);
386 // Speed up test execution.
387 ret->set_idle_seconds(1);
388 ret->set_retry_seconds(1);
389 fake_hardware_.SetIsOfficialBuild(false);
390 return ret;
391 }
392
393 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700394 using AnyHttpFetcherFactory::NewSmallFetcher;
Tao Bao642b32b2019-01-02 15:33:42 -0800395 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
396 return NewLargeFetcher(proxy_resolver);
397 }
398
399 bool IsMulti() const override { return true; }
400};
401
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800402//
403// Infrastructure for type tests of HTTP fetcher.
404// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
405//
406
407// Fixture class template. We use an explicit constraint to guarantee that it
408// can only be instantiated with an AnyHttpFetcherTest type, see:
409// http://www2.research.att.com/~bs/bs_faq2.html#constraints
410template <typename T>
411class HttpFetcherTest : public ::testing::Test {
412 public:
Qijiang Fanb0b6cc22020-10-15 21:54:11 +0900413#if BASE_VER < 780000 // Android
Alex Deymo535f3b72015-08-07 10:51:32 -0700414 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700415 brillo::BaseMessageLoop loop_{&base_loop_};
Qijiang Fanb0b6cc22020-10-15 21:54:11 +0900416#else // Chrome OS
417 base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
418 brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
419#endif // BASE_VER < 780000
Alex Deymo60ca1a72015-06-18 18:19:15 -0700420
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800421 T test_;
422
Alex Deymo60ca1a72015-06-18 18:19:15 -0700423 protected:
Amin Hassanib2689592019-01-13 17:04:28 -0800424 HttpFetcherTest() { loop_.SetAsCurrent(); }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700425
426 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700427 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700428 }
429
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800430 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700431 static void TypeConstraint(T* a) {
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700432 AnyHttpFetcherFactory* b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700433 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700434 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800435 }
436};
437
438// Test case types list.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700439typedef ::testing::Types<LibcurlHttpFetcherFactory,
440 MockHttpFetcherFactory,
441 MultiRangeHttpFetcherFactory,
442 FileFetcherFactory,
443 MultiRangeHttpFetcherOverFileFetcherFactory>
Alex Deymo2c131bb2016-05-26 16:43:13 -0700444 HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000445TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
446
rspangler@google.com49fdf182009-10-10 00:57:34 +0000447class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000448 public:
Alex Deymofdd6dec2016-03-03 22:35:43 -0800449 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800450
Amin Hassani0cd9d772018-07-31 23:55:43 -0700451 bool ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymofdd6dec2016-03-03 22:35:43 -0800452 const void* bytes,
453 size_t length) override {
454 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800455 // Update counters
456 times_received_bytes_called_++;
Amin Hassani0cd9d772018-07-31 23:55:43 -0700457 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000458 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800459
Alex Deymo610277e2014-11-11 21:18:11 -0800460 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800461 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800462 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800463 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800464 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700465 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800466
467 // Update counter
468 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000469 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800470
Alex Deymo610277e2014-11-11 21:18:11 -0800471 void TransferTerminated(HttpFetcher* fetcher) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800472 times_transfer_terminated_called_++;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700473 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800474 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800475
Gilad Arnold48085ba2011-11-16 09:36:08 -0800476 // Are we expecting an error response? (default: no)
Alex Deymofdd6dec2016-03-03 22:35:43 -0800477 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800478
479 // Counters for callback invocations.
Alex Deymofdd6dec2016-03-03 22:35:43 -0800480 int times_transfer_complete_called_{0};
481 int times_transfer_terminated_called_{0};
482 int times_received_bytes_called_{0};
483
484 // The received data bytes.
485 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000486};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000487
Alex Deymo60ca1a72015-06-18 18:19:15 -0700488void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
489 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000490}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000491
492TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700493 HttpFetcherTestDelegate delegate;
494 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
495 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000496
Alex Deymo60ca1a72015-06-18 18:19:15 -0700497 unique_ptr<HttpServer> server(this->test_.CreateServer());
498 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000499
Amin Hassanib2689592019-01-13 17:04:28 -0800500 this->loop_.PostTask(FROM_HERE,
501 base::Bind(StartTransfer,
502 fetcher.get(),
503 this->test_.SmallUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700504 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800505 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000506}
507
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700508TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700509 HttpFetcherTestDelegate delegate;
510 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
511 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700512
Alex Deymo60ca1a72015-06-18 18:19:15 -0700513 unique_ptr<HttpServer> server(this->test_.CreateServer());
514 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700515
Amin Hassanib2689592019-01-13 17:04:28 -0800516 this->loop_.PostTask(
517 FROM_HERE,
518 base::Bind(
519 StartTransfer, fetcher.get(), this->test_.BigUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700520 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800521 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700522}
523
Gilad Arnold48085ba2011-11-16 09:36:08 -0800524// Issue #9648: when server returns an error HTTP response, the fetcher needs to
525// terminate transfer prematurely, rather than try to process the error payload.
526TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800527 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800528 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700529 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800530
Alex Deymo60ca1a72015-06-18 18:19:15 -0700531 // Delegate should expect an error response.
532 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800533
Alex Deymo60ca1a72015-06-18 18:19:15 -0700534 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
535 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800536
Alex Deymo60ca1a72015-06-18 18:19:15 -0700537 unique_ptr<HttpServer> server(this->test_.CreateServer());
538 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800539
Amin Hassanib2689592019-01-13 17:04:28 -0800540 this->loop_.PostTask(FROM_HERE,
541 base::Bind(StartTransfer,
542 fetcher.get(),
543 this->test_.ErrorUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700544 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800545
Alex Deymo60ca1a72015-06-18 18:19:15 -0700546 // Make sure that no bytes were received.
Alex Deymo71f67622017-02-03 21:30:24 -0800547 EXPECT_EQ(0, delegate.times_received_bytes_called_);
548 EXPECT_EQ(0U, fetcher->GetBytesDownloaded());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800549
Alex Deymo60ca1a72015-06-18 18:19:15 -0700550 // Make sure that transfer completion was signaled once, and no termination
551 // was signaled.
Alex Deymo71f67622017-02-03 21:30:24 -0800552 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
553 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800554}
555
Alex Deymofdd6dec2016-03-03 22:35:43 -0800556TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700557 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymofdd6dec2016-03-03 22:35:43 -0800558 return;
559
560 HttpFetcherTestDelegate delegate;
561 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
562 fetcher->set_delegate(&delegate);
563 fetcher->SetHeader("User-Agent", "MyTest");
564 fetcher->SetHeader("user-agent", "Override that header");
565 fetcher->SetHeader("Authorization", "Basic user:passwd");
566
567 // Invalid headers.
568 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
569 fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
570
571 // Hide Accept header normally added by default.
572 fetcher->SetHeader("Accept", "");
573
574 PythonHttpServer server;
575 int port = server.GetPort();
576 ASSERT_TRUE(server.started_);
577
Alex Deymo2c131bb2016-05-26 16:43:13 -0700578 this->loop_.PostTask(
579 FROM_HERE,
580 base::Bind(StartTransfer,
581 fetcher.get(),
582 LocalServerUrlForPath(port, "/echo-headers")));
Alex Deymofdd6dec2016-03-03 22:35:43 -0800583 this->loop_.Run();
584
585 EXPECT_NE(string::npos,
586 delegate.data.find("user-agent: Override that header\r\n"));
587 EXPECT_NE(string::npos,
588 delegate.data.find("Authorization: Basic user:passwd\r\n"));
589
590 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
591 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
592 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
593}
594
rspangler@google.com49fdf182009-10-10 00:57:34 +0000595class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
596 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700597 bool ReceivedBytes(HttpFetcher* fetcher,
598 const void* /* bytes */,
599 size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000600 CHECK(!paused_);
601 paused_ = true;
602 fetcher->Pause();
Amin Hassani0cd9d772018-07-31 23:55:43 -0700603 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000604 }
Alex Deymo610277e2014-11-11 21:18:11 -0800605 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700606 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000607 }
Amin Hassanib2689592019-01-13 17:04:28 -0800608 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000609 void Unpause() {
610 CHECK(paused_);
611 paused_ = false;
612 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000613 }
614 bool paused_;
615 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000616};
617
Alex Deymo60ca1a72015-06-18 18:19:15 -0700618void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
619 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000620 if (delegate->paused_)
621 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700622 // Update the task id with the new scheduled callback.
623 *my_id = MessageLoop::current()->PostDelayedTask(
624 FROM_HERE,
625 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
626 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000627}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000628
629TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800630 PausingHttpFetcherTestDelegate delegate;
631 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
632 delegate.paused_ = false;
633 delegate.fetcher_ = fetcher.get();
634 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000635
Alex Deymof2858572016-02-25 11:20:13 -0800636 unique_ptr<HttpServer> server(this->test_.CreateServer());
637 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800638
Alex Deymof2858572016-02-25 11:20:13 -0800639 MessageLoop::TaskId callback_id;
640 callback_id = this->loop_.PostDelayedTask(
641 FROM_HERE,
642 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
643 base::TimeDelta::FromMilliseconds(200));
644 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000645
Alex Deymof2858572016-02-25 11:20:13 -0800646 this->loop_.Run();
647 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
648}
649
650// This test will pause the fetcher while the download is not yet started
651// because it is waiting for the proxy to be resolved.
652TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700653 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymof2858572016-02-25 11:20:13 -0800654 return;
655 MockProxyResolver mock_resolver;
656 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
657
658 // Saved arguments from the proxy call.
Alex Deymo35821942017-02-05 04:36:02 +0000659 ProxiesResolvedFn proxy_callback;
660 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _))
661 .WillOnce(DoAll(SaveArg<1>(&proxy_callback), Return(true)));
Alex Deymof2858572016-02-25 11:20:13 -0800662 fetcher->BeginTransfer("http://fake_url");
663 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
664
665 // Pausing and unpausing while resolving the proxy should not affect anything.
666 fetcher->Pause();
667 fetcher->Unpause();
668 fetcher->Pause();
669 // Proxy resolver comes back after we paused the fetcher.
Alex Deymoc00ec562017-02-05 04:36:02 +0000670 ASSERT_FALSE(proxy_callback.is_null());
Alex Deymo35821942017-02-05 04:36:02 +0000671 proxy_callback.Run({1, kNoProxy});
rspangler@google.com49fdf182009-10-10 00:57:34 +0000672}
673
rspangler@google.com49fdf182009-10-10 00:57:34 +0000674class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
675 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700676 bool ReceivedBytes(HttpFetcher* fetcher,
677 const void* bytes,
678 size_t length) override {
679 return true;
680 }
Alex Deymo610277e2014-11-11 21:18:11 -0800681 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800682 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700683 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000684 }
Alex Deymo610277e2014-11-11 21:18:11 -0800685 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800686 EXPECT_EQ(fetcher, fetcher_.get());
687 EXPECT_FALSE(once_);
688 EXPECT_TRUE(callback_once_);
689 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700690 // The fetcher could have a callback scheduled on the ProxyResolver that
691 // can fire after this callback. We wait until the end of the test to
692 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800693 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000694 void TerminateTransfer() {
695 CHECK(once_);
696 once_ = false;
697 fetcher_->TerminateTransfer();
698 }
Amin Hassanib2689592019-01-13 17:04:28 -0800699 void EndLoop() { MessageLoop::current()->BreakLoop(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000700 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800701 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700702 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000703};
704
Alex Deymo60ca1a72015-06-18 18:19:15 -0700705void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
706 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000707 if (delegate->once_) {
708 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700709 *my_id = MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800710 FROM_HERE, base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000711 } else {
712 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700713 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000714 }
715}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000716
717TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700718 AbortingHttpFetcherTestDelegate delegate;
719 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
720 delegate.once_ = true;
721 delegate.callback_once_ = true;
722 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000723
Alex Deymo60ca1a72015-06-18 18:19:15 -0700724 unique_ptr<HttpServer> server(this->test_.CreateServer());
725 this->test_.IgnoreServerAborting(server.get());
726 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800727
Alex Deymo60ca1a72015-06-18 18:19:15 -0700728 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000729
Alex Deymo60ca1a72015-06-18 18:19:15 -0700730 task_id = this->loop_.PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800731 FROM_HERE, base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700732 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
733
734 this->loop_.Run();
735 CHECK(!delegate.once_);
736 CHECK(!delegate.callback_once_);
737 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000738}
739
Alex Deymo71f67622017-02-03 21:30:24 -0800740TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
741 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
742 return;
743 MockProxyResolver mock_resolver;
744 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
745
746 HttpFetcherTestDelegate delegate;
747 fetcher->set_delegate(&delegate);
748
749 EXPECT_CALL(mock_resolver, GetProxiesForUrl(_, _)).WillOnce(Return(123));
750 fetcher->BeginTransfer("http://fake_url");
751 // Run the message loop until idle. This must call the MockProxyResolver with
752 // the request.
753 while (this->loop_.RunOnce(false)) {
754 }
755 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
756
757 EXPECT_CALL(mock_resolver, CancelProxyRequest(123)).WillOnce(Return(true));
758
759 // Terminate the transfer right before the proxy resolution response.
760 fetcher->TerminateTransfer();
761 EXPECT_EQ(0, delegate.times_received_bytes_called_);
762 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
763 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
764}
765
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000766class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
767 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700768 bool ReceivedBytes(HttpFetcher* fetcher,
769 const void* bytes,
770 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800771 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700772 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000773 }
Alex Deymo610277e2014-11-11 21:18:11 -0800774 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700775 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800776 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700777 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000778 }
Amin Hassanib2689592019-01-13 17:04:28 -0800779 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000780 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000781};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000782
783TYPED_TEST(HttpFetcherTest, FlakyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700784 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000785 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000786 {
787 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700788 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000789 fetcher->set_delegate(&delegate);
790
Ben Chan02f7c1d2014-10-18 15:18:02 -0700791 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800792 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000793
Amin Hassanib2689592019-01-13 17:04:28 -0800794 this->loop_.PostTask(FROM_HERE,
795 base::Bind(&StartTransfer,
796 fetcher.get(),
797 LocalServerUrlForPath(
798 server->GetPort(),
799 base::StringPrintf("/flaky/%d/%d/%d/%d",
800 kBigLength,
801 kFlakyTruncateLength,
802 kFlakySleepEvery,
803 kFlakySleepSecs))));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700804 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000805
806 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800807 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800808 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000809 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
810 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
811 }
812 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000813}
814
Chris Sosa0a364bb2014-06-10 18:18:24 -0700815// This delegate kills the server attached to it after receiving any bytes.
816// This can be used for testing what happens when you try to fetch data and
817// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700818class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
819 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700820 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700821 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700822
Alex Deymo610277e2014-11-11 21:18:11 -0800823 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700824 if (server_) {
825 LOG(INFO) << "Stopping server in destructor";
Alex Deymob20de692017-02-05 07:47:37 +0000826 server_.reset();
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700827 LOG(INFO) << "server stopped";
828 }
829 }
830
Amin Hassani0cd9d772018-07-31 23:55:43 -0700831 bool ReceivedBytes(HttpFetcher* fetcher,
832 const void* bytes,
833 size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700834 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700835 LOG(INFO) << "Stopping server in ReceivedBytes";
Alex Deymob20de692017-02-05 07:47:37 +0000836 server_.reset();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700837 LOG(INFO) << "server stopped";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700838 }
Amin Hassani0cd9d772018-07-31 23:55:43 -0700839 return true;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700840 }
Alex Deymo610277e2014-11-11 21:18:11 -0800841 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700842 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700843 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymob20de692017-02-05 07:47:37 +0000844 times_transfer_complete_called_++;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700845 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700846 }
Alex Deymo610277e2014-11-11 21:18:11 -0800847 void TransferTerminated(HttpFetcher* fetcher) override {
Alex Deymob20de692017-02-05 07:47:37 +0000848 times_transfer_terminated_called_++;
849 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800850 }
Alex Deymob20de692017-02-05 07:47:37 +0000851 unique_ptr<PythonHttpServer> server_;
852 int times_transfer_terminated_called_{0};
853 int times_transfer_complete_called_{0};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700854};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700855
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700856TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700857 // This test ensures that a fetcher responds correctly when a server isn't
858 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800859 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700860 return;
Alex Deymob20de692017-02-05 07:47:37 +0000861 FailureHttpFetcherTestDelegate delegate(nullptr);
862 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
863 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700864
Alex Deymob20de692017-02-05 07:47:37 +0000865 this->loop_.PostTask(
866 FROM_HERE,
867 base::Bind(
868 StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
869 this->loop_.Run();
870 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
871 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700872
Alex Deymob20de692017-02-05 07:47:37 +0000873 // Exiting and testing happens in the delegate
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700874}
875
Alex Deymof123ae22015-09-24 14:59:43 -0700876TYPED_TEST(HttpFetcherTest, NoResponseTest) {
877 // This test starts a new http server but the server doesn't respond and just
878 // closes the connection.
879 if (this->test_.IsMock())
880 return;
881
882 PythonHttpServer* server = new PythonHttpServer();
883 int port = server->GetPort();
884 ASSERT_TRUE(server->started_);
885
886 // Handles destruction and claims ownership.
887 FailureHttpFetcherTestDelegate delegate(server);
888 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
889 fetcher->set_delegate(&delegate);
890 // The server will not reply at all, so we can limit the execution time of the
891 // test by reducing the low-speed timeout to something small. The test will
892 // finish once the TimeoutCallback() triggers (every second) and the timeout
893 // expired.
894 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
895
Amin Hassanib2689592019-01-13 17:04:28 -0800896 this->loop_.PostTask(
897 FROM_HERE,
898 base::Bind(
899 StartTransfer, fetcher.get(), LocalServerUrlForPath(port, "/hang")));
Alex Deymof123ae22015-09-24 14:59:43 -0700900 this->loop_.Run();
Alex Deymob20de692017-02-05 07:47:37 +0000901 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
902 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Alex Deymof123ae22015-09-24 14:59:43 -0700903
904 // Check that no other callback runs in the next two seconds. That would
905 // indicate a leaked callback.
906 bool timeout = false;
Luis Hector Chavezf1cf3482016-07-19 14:29:19 -0700907 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
908 base::Unretained(&timeout));
Amin Hassanib2689592019-01-13 17:04:28 -0800909 this->loop_.PostDelayedTask(
910 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
Alex Deymof123ae22015-09-24 14:59:43 -0700911 EXPECT_TRUE(this->loop_.RunOnce(true));
912 EXPECT_TRUE(timeout);
913}
914
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700915TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700916 // This test starts a new http server and kills it after receiving its first
917 // set of bytes. It test whether or not our fetcher eventually gives up on
918 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800919 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700920 return;
Alex Deymob20de692017-02-05 07:47:37 +0000921 PythonHttpServer* server = new PythonHttpServer();
922 int port = server->GetPort();
923 ASSERT_TRUE(server->started_);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700924
Alex Deymob20de692017-02-05 07:47:37 +0000925 // Handles destruction and claims ownership.
926 FailureHttpFetcherTestDelegate delegate(server);
927 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
928 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700929
Alex Deymob20de692017-02-05 07:47:37 +0000930 this->loop_.PostTask(
931 FROM_HERE,
932 base::Bind(StartTransfer,
933 fetcher.get(),
934 LocalServerUrlForPath(port,
935 base::StringPrintf("/flaky/%d/%d/%d/%d",
936 kBigLength,
937 kFlakyTruncateLength,
938 kFlakySleepEvery,
939 kFlakySleepSecs))));
940 this->loop_.Run();
941 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
942 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700943
Alex Deymob20de692017-02-05 07:47:37 +0000944 // Exiting and testing happens in the delegate
945}
946
947// Test that we can cancel a transfer while it is still trying to connect to the
948// server. This test kills the server after a few bytes are received.
949TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
950 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
951 return;
952
953 PythonHttpServer* server = new PythonHttpServer();
954 int port = server->GetPort();
955 ASSERT_TRUE(server->started_);
956
957 // Handles destruction and claims ownership.
958 FailureHttpFetcherTestDelegate delegate(server);
959 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
960 fetcher->set_delegate(&delegate);
961
962 this->loop_.PostTask(
963 FROM_HERE,
964 base::Bind(StartTransfer,
965 fetcher.get(),
966 LocalServerUrlForPath(port,
967 base::StringPrintf("/flaky/%d/%d/%d/%d",
968 kBigLength,
969 kFlakyTruncateLength,
970 kFlakySleepEvery,
971 kFlakySleepSecs))));
972 // Terminating the transfer after 3 seconds gives it a chance to contact the
973 // server and enter the retry loop.
974 this->loop_.PostDelayedTask(FROM_HERE,
975 base::Bind(&HttpFetcher::TerminateTransfer,
976 base::Unretained(fetcher.get())),
977 base::TimeDelta::FromSeconds(3));
978
979 // Exiting and testing happens in the delegate.
980 this->loop_.Run();
981 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
982 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
983
984 // Check that no other callback runs in the next two seconds. That would
985 // indicate a leaked callback.
986 bool timeout = false;
987 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
988 base::Unretained(&timeout));
989 this->loop_.PostDelayedTask(
990 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
991 EXPECT_TRUE(this->loop_.RunOnce(true));
992 EXPECT_TRUE(timeout);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700993}
994
Amin Hassanib2689592019-01-13 17:04:28 -0800995const HttpResponseCode kRedirectCodes[] = {kHttpResponseMovedPermanently,
996 kHttpResponseFound,
997 kHttpResponseSeeOther,
998 kHttpResponseTempRedirect};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700999
1000class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
1001 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001002 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001003 : expected_successful_(expected_successful) {}
Amin Hassani0cd9d772018-07-31 23:55:43 -07001004 bool ReceivedBytes(HttpFetcher* fetcher,
1005 const void* bytes,
1006 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001007 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001008 return true;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001009 }
Alex Deymo610277e2014-11-11 21:18:11 -08001010 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001011 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001012 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001013 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001014 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001015 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
1016 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -07001017 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001018 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001019 }
Amin Hassanib2689592019-01-13 17:04:28 -08001020 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001021 bool expected_successful_;
1022 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001023};
1024
1025// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001026void RedirectTest(const HttpServer* server,
1027 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001028 const string& url,
1029 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001030 RedirectHttpFetcherTestDelegate delegate(expected_successful);
1031 unique_ptr<HttpFetcher> fetcher(http_fetcher);
1032 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001033
Amin Hassanib2689592019-01-13 17:04:28 -08001034 MessageLoop::current()->PostTask(
1035 FROM_HERE,
1036 base::Bind(StartTransfer,
1037 fetcher.get(),
1038 LocalServerUrlForPath(server->GetPort(), url)));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001039 MessageLoop::current()->Run();
1040 if (expected_successful) {
1041 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -08001042 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -07001043 for (int i = 0; i < kMediumLength; i += 10) {
1044 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
1045 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001046 }
1047 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001048}
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001049
1050TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001051 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001052 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001053
Ben Chan02f7c1d2014-10-18 15:18:02 -07001054 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001055 ASSERT_TRUE(server->started_);
1056
hscham00b6aa22020-02-20 12:32:06 +09001057 for (size_t c = 0; c < base::size(kRedirectCodes); ++c) {
Amin Hassanib2689592019-01-13 17:04:28 -08001058 const string url = base::StringPrintf(
1059 "/redirect/%d/download/%d", kRedirectCodes[c], kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001060 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001061 }
1062}
1063
1064TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001065 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001066 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001067
Ben Chan02f7c1d2014-10-18 15:18:02 -07001068 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001069 ASSERT_TRUE(server->started_);
1070
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001071 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001072 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001073 url += base::StringPrintf("/redirect/%d",
hscham00b6aa22020-02-20 12:32:06 +09001074 kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001075 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001076 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001077 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001078}
1079
1080TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001081 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001082 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001083
Ben Chan02f7c1d2014-10-18 15:18:02 -07001084 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001085 ASSERT_TRUE(server->started_);
1086
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001087 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001088 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001089 url += base::StringPrintf("/redirect/%d",
hscham00b6aa22020-02-20 12:32:06 +09001090 kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001091 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001092 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001093 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001094}
1095
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001096class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1097 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001098 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001099 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001100
Amin Hassani0cd9d772018-07-31 23:55:43 -07001101 bool ReceivedBytes(HttpFetcher* fetcher,
1102 const void* bytes,
1103 size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001104 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001105 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001106 return true;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001107 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001108
Alex Deymo610277e2014-11-11 21:18:11 -08001109 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001110 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001111 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001112 if (expected_response_code_ != 0)
1113 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001114 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -07001115 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001116 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001117 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001118
Amin Hassanib2689592019-01-13 17:04:28 -08001119 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001120
Ben Chan02f7c1d2014-10-18 15:18:02 -07001121 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001122 int expected_response_code_;
1123 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001124};
1125
1126void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -03001127 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001128 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -07001129 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001130 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -08001131 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001132 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001133 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1134 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001135
Alex Deymo60ca1a72015-06-18 18:19:15 -07001136 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -08001137 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001138 ASSERT_TRUE(multi_fetcher);
1139 multi_fetcher->ClearRanges();
1140 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
Amin Hassanib2689592019-01-13 17:04:28 -08001141 e = ranges.end();
1142 it != e;
1143 ++it) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001144 string tmp_str = base::StringPrintf("%jd+", it->first);
1145 if (it->second > 0) {
1146 base::StringAppendF(&tmp_str, "%jd", it->second);
1147 multi_fetcher->AddRange(it->first, it->second);
1148 } else {
1149 base::StringAppendF(&tmp_str, "?");
1150 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001151 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001152 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001153 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001154 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001155 multi_fetcher->set_delegate(&delegate);
1156
1157 MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -08001158 FROM_HERE, base::Bind(StartTransfer, multi_fetcher, url));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001159 MessageLoop::current()->Run();
1160
1161 EXPECT_EQ(expected_size, delegate.data.size());
1162 EXPECT_EQ(expected_prefix,
1163 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001164}
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001165
Darin Petkov9ce452b2010-11-17 14:33:28 -08001166TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001167 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001168 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001169
Ben Chan02f7c1d2014-10-18 15:18:02 -07001170 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001171 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001172
Ben Chanf9cb98c2014-09-21 18:31:30 -07001173 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001174 ranges.push_back(make_pair(0, 25));
Tao Bao642b32b2019-01-02 15:33:42 -08001175 ranges.push_back(make_pair(99, 17));
1176 MultiTest(this->test_.NewLargeFetcher(),
1177 this->test_.fake_hardware(),
1178 this->test_.BigUrl(server->GetPort()),
1179 ranges,
1180 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1181 25 + 17,
1182 this->test_.IsFileFetcher() ? kHttpResponseOk
1183 : kHttpResponsePartialContent);
1184}
1185
1186TYPED_TEST(HttpFetcherTest, MultiHttpFetcherUnspecifiedEndTest) {
1187 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1188 return;
1189
1190 unique_ptr<HttpServer> server(this->test_.CreateServer());
1191 ASSERT_TRUE(server->started_);
1192
1193 vector<pair<off_t, off_t>> ranges;
1194 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001195 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001196 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001197 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001198 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001199 ranges,
1200 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001201 kBigLength - (99 - 25),
1202 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001203}
1204
1205TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001206 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001207 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001208
Ben Chan02f7c1d2014-10-18 15:18:02 -07001209 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001210 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001211
Ben Chanf9cb98c2014-09-21 18:31:30 -07001212 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001213 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001214 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001215 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001216 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001217 ranges,
1218 "abcdefghijabcdefghijabcd",
1219 24,
Tao Bao642b32b2019-01-02 15:33:42 -08001220 this->test_.IsFileFetcher() ? kHttpResponseOk
1221 : kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001222}
1223
1224TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001225 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001226 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001227
Ben Chan02f7c1d2014-10-18 15:18:02 -07001228 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001229 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001230
Ben Chanf9cb98c2014-09-21 18:31:30 -07001231 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001232 ranges.push_back(make_pair(kBigLength - 2, 0));
1233 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001234 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001235 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001236 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001237 ranges,
1238 "ijhij",
1239 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001240 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001241}
1242
1243TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001244 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001245 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001246
Ben Chan02f7c1d2014-10-18 15:18:02 -07001247 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001248 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001249
Ben Chanf9cb98c2014-09-21 18:31:30 -07001250 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001251 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001252 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001253 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001254 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001255 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001256 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001257 ranges,
1258 "ij",
1259 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001260 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001261 ranges.push_back(make_pair(0, 5));
1262 }
1263}
1264
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001265// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1266// should retry with other proxies listed before giving up.
1267//
1268// (1) successful recovery: The offset fetch will fail twice but succeed with
1269// the third proxy.
1270TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001271 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001272 return;
1273
Ben Chan02f7c1d2014-10-18 15:18:02 -07001274 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001275 ASSERT_TRUE(server->started_);
1276
Ben Chanf9cb98c2014-09-21 18:31:30 -07001277 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001278 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001279 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001280 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001281 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001282 LocalServerUrlForPath(
1283 server->GetPort(),
1284 base::StringPrintf("/error-if-offset/%d/2", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001285 ranges,
1286 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1287 kBigLength - (99 - 25),
1288 kHttpResponsePartialContent);
1289}
1290
1291// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1292// fetcher will signal a (failed) completed transfer to the delegate.
1293TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001294 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001295 return;
1296
Ben Chan02f7c1d2014-10-18 15:18:02 -07001297 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001298 ASSERT_TRUE(server->started_);
1299
Ben Chanf9cb98c2014-09-21 18:31:30 -07001300 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001301 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001302 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001303 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001304 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001305 LocalServerUrlForPath(
1306 server->GetPort(),
1307 base::StringPrintf("/error-if-offset/%d/3", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001308 ranges,
1309 "abcdefghijabcdefghijabcde", // only received the first chunk
1310 25,
1311 kHttpResponseUndefined);
1312}
1313
Alex Deymo4ea2d922017-02-05 07:35:32 +00001314// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1315class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1316 public:
1317 explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1318 : terminate_trigger_bytes_(terminate_trigger_bytes) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001319
Amin Hassani0cd9d772018-07-31 23:55:43 -07001320 bool ReceivedBytes(HttpFetcher* fetcher,
Alex Deymo4ea2d922017-02-05 07:35:32 +00001321 const void* bytes,
1322 size_t length) override {
1323 LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
1324 EXPECT_EQ(fetcher, fetcher_.get());
Tao Bao642b32b2019-01-02 15:33:42 -08001325 bool should_terminate = false;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001326 if (bytes_downloaded_ < terminate_trigger_bytes_ &&
1327 bytes_downloaded_ + length >= terminate_trigger_bytes_) {
1328 MessageLoop::current()->PostTask(
1329 FROM_HERE,
1330 base::Bind(&HttpFetcher::TerminateTransfer,
1331 base::Unretained(fetcher_.get())));
Tao Bao642b32b2019-01-02 15:33:42 -08001332 should_terminate = true;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001333 }
1334 bytes_downloaded_ += length;
Tao Bao642b32b2019-01-02 15:33:42 -08001335 return !should_terminate;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001336 }
1337
1338 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1339 ADD_FAILURE() << "TransferComplete called but expected a failure";
1340 // Destroy the fetcher (because we're allowed to).
1341 fetcher_.reset(nullptr);
1342 MessageLoop::current()->BreakLoop();
1343 }
1344
1345 void TransferTerminated(HttpFetcher* fetcher) override {
1346 // Destroy the fetcher (because we're allowed to).
1347 fetcher_.reset(nullptr);
1348 MessageLoop::current()->BreakLoop();
1349 }
1350
1351 unique_ptr<HttpFetcher> fetcher_;
1352 size_t bytes_downloaded_{0};
1353 size_t terminate_trigger_bytes_;
1354};
Alex Deymo4ea2d922017-02-05 07:35:32 +00001355
1356TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
1357 if (!this->test_.IsMulti())
1358 return;
1359 const size_t kRangeTrigger = 1000;
1360 MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
1361
1362 unique_ptr<HttpServer> server(this->test_.CreateServer());
1363 ASSERT_TRUE(server->started_);
1364
1365 MultiRangeHttpFetcher* multi_fetcher =
1366 static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
1367 ASSERT_TRUE(multi_fetcher);
1368 // Transfer ownership of the fetcher to the delegate.
1369 delegate.fetcher_.reset(multi_fetcher);
1370 multi_fetcher->set_delegate(&delegate);
1371
1372 multi_fetcher->ClearRanges();
1373 multi_fetcher->AddRange(45, kRangeTrigger);
1374 multi_fetcher->AddRange(2000, 100);
1375
1376 this->test_.fake_hardware()->SetIsOfficialBuild(false);
1377
1378 StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
1379 MessageLoop::current()->Run();
1380
1381 // Check that the delegate made it to the trigger point.
1382 EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
1383}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001384
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001385class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001386 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -07001387 bool ReceivedBytes(HttpFetcher* fetcher,
1388 const void* bytes,
1389 size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001390 ADD_FAILURE();
Amin Hassani0cd9d772018-07-31 23:55:43 -07001391 return true;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001392 }
Alex Deymo610277e2014-11-11 21:18:11 -08001393 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001394 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001395 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001396 }
Amin Hassanib2689592019-01-13 17:04:28 -08001397 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001398};
1399
Kelvin Zhangf0c73d42021-09-07 10:34:26 -07001400void BlockedTransferTestHelper(AnyHttpFetcherFactory* fetcher_test,
Alex Deymo60ca1a72015-06-18 18:19:15 -07001401 bool is_official_build) {
1402 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1403 return;
1404
1405 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1406 ASSERT_TRUE(server->started_);
1407
1408 BlockedTransferTestDelegate delegate;
1409 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1410 LOG(INFO) << "is_official_build: " << is_official_build;
1411 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001412 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001413 fetcher->set_delegate(&delegate);
1414
Amin Hassanib2689592019-01-13 17:04:28 -08001415 MessageLoop::current()->PostTask(
1416 FROM_HERE,
1417 base::Bind(
1418 StartTransfer,
1419 fetcher.get(),
1420 LocalServerUrlForPath(server->GetPort(),
1421 fetcher_test->SmallUrl(server->GetPort()))));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001422 MessageLoop::current()->Run();
1423}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001424
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001425TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001426 BlockedTransferTestHelper(&this->test_, false);
1427}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001428
Alex Deymo60ca1a72015-06-18 18:19:15 -07001429TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1430 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001431}
1432
Kelvin Zhangf0c73d42021-09-07 10:34:26 -07001433} // namespace
1434
rspangler@google.com49fdf182009-10-10 00:57:34 +00001435} // namespace chromeos_update_engine