blob: 99ea99bdc960659bdfd7c38b0b6b6a5c5588fbca [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
100class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000101 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800102 // This makes it an abstract class (dirty but works).
103 virtual ~HttpServer() = 0;
104
Amin Hassanib2689592019-01-13 17:04:28 -0800105 virtual in_port_t GetPort() const { return 0; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700106
rspangler@google.com49fdf182009-10-10 00:57:34 +0000107 bool started_;
108};
109
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800110HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000111
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800112class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000113 public:
Amin Hassanib2689592019-01-13 17:04:28 -0800114 NullHttpServer() { started_ = true; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000115};
116
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800117class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000118 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700119 PythonHttpServer() : port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000120 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700121
122 // Spawn the server process.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700123 unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
Sen Jiang260f03b2016-03-21 15:34:58 -0700124 http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
Alex Deymo535f3b72015-08-07 10:51:32 -0700125 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
126
127 if (!http_server->Start()) {
128 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000129 return;
130 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700131 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700132
133 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700134 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700135 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
136 if (!stdout)
137 return;
138
139 vector<char> buf(128);
140 string line;
141 while (line.find('\n') == string::npos) {
142 size_t read;
143 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
144 ADD_FAILURE() << "error reading http server stdout";
145 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700146 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700147 line.append(buf.data(), read);
148 if (read == 0)
149 break;
150 }
151 // Parse the port from the output line.
152 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
153 if (line.size() < listening_msg_prefix_len) {
154 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700155 return;
156 }
157
Alex Deymo535f3b72015-08-07 10:51:32 -0700158 EXPECT_EQ(kServerListeningMsgPrefix,
159 line.substr(0, listening_msg_prefix_len));
160 string port_str = line.substr(listening_msg_prefix_len);
161 port_str.resize(port_str.find('\n'));
162 EXPECT_TRUE(base::StringToUint(port_str, &port_));
163
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700164 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700165 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700166
167 // Any failure before this point will SIGKILL the test server if started
168 // when the |http_server| goes out of scope.
169 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000170 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800171
rspangler@google.com49fdf182009-10-10 00:57:34 +0000172 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700173 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700174 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000175 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700176 // Wait up to 10 seconds for the process to finish. Destroying the process
177 // will kill it with a SIGKILL otherwise.
178 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000179 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800180
Amin Hassanib2689592019-01-13 17:04:28 -0800181 in_port_t GetPort() const override { return port_; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700182
183 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700184 static const char* kServerListeningMsgPrefix;
185
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700186 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700187 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000188};
189
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700190const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
191
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800192//
193// Class hierarchy for HTTP fetcher test wrappers.
194//
195
196class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000197 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700198 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700199 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700200
Alex Deymof2858572016-02-25 11:20:13 -0800201 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
202 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
203 proxy_resolver_.set_num_proxies(num_proxies);
204 return NewLargeFetcher(&proxy_resolver_);
205 }
Amin Hassanib2689592019-01-13 17:04:28 -0800206 HttpFetcher* NewLargeFetcher() { return NewLargeFetcher(1); }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800207
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;
Tao Bao642b32b2019-01-02 15:33:42 -0800221 virtual bool IsFileFetcher() const = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800222
223 virtual void IgnoreServerAborting(HttpServer* server) const {}
224
Alex Deymo60ca1a72015-06-18 18:19:15 -0700225 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800226
Amin Hassanib2689592019-01-13 17:04:28 -0800227 FakeHardware* fake_hardware() { return &fake_hardware_; }
Alex Deymoc1c17b42015-11-23 03:53:15 -0300228
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800229 protected:
230 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300231 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800232};
233
234class MockHttpFetcherTest : public AnyHttpFetcherTest {
235 public:
236 // Necessary to unhide the definition in the base class.
237 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800238 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700239 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800240 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800241 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800242 }
243
244 // Necessary to unhide the definition in the base class.
245 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800246 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
247 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800248 }
249
Alex Deymo610277e2014-11-11 21:18:11 -0800250 bool IsMock() const override { return true; }
251 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700252 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800253 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800254
Amin Hassanib2689592019-01-13 17:04:28 -0800255 HttpServer* CreateServer() override { return new NullHttpServer; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800256};
257
258class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
259 public:
260 // Necessary to unhide the definition in the base class.
261 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800262 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
263 LibcurlHttpFetcher* ret =
264 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700265 // Speed up test execution.
266 ret->set_idle_seconds(1);
267 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300268 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000269 return ret;
270 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800271
272 // Necessary to unhide the definition in the base class.
273 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800274 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
275 return NewLargeFetcher(proxy_resolver);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000276 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800277
Alex Deymo610277e2014-11-11 21:18:11 -0800278 string BigUrl(in_port_t port) const override {
Amin Hassanib2689592019-01-13 17:04:28 -0800279 return LocalServerUrlForPath(
280 port, base::StringPrintf("/download/%d", kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000281 }
Alex Deymo610277e2014-11-11 21:18:11 -0800282 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700283 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000284 }
Alex Deymo610277e2014-11-11 21:18:11 -0800285 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700286 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800287 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800288
Alex Deymo610277e2014-11-11 21:18:11 -0800289 bool IsMock() const override { return false; }
290 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700291 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800292 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800293
Alex Deymo610277e2014-11-11 21:18:11 -0800294 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700295 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700296 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800297
Amin Hassanib2689592019-01-13 17:04:28 -0800298 HttpServer* CreateServer() override { return new PythonHttpServer; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000299};
300
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800301class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700302 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800303 // Necessary to unhide the definition in the base class.
304 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800305 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
306 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
307 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800308 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800309 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700310 // Speed up test execution.
311 ret->set_idle_seconds(1);
312 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300313 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700314 return ret;
315 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800316
317 // Necessary to unhide the definition in the base class.
318 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800319 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
320 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800321 }
322
Alex Deymo610277e2014-11-11 21:18:11 -0800323 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700324};
325
Alex Deymo2c131bb2016-05-26 16:43:13 -0700326class FileFetcherTest : public AnyHttpFetcherTest {
327 public:
328 // Necessary to unhide the definition in the base class.
329 using AnyHttpFetcherTest::NewLargeFetcher;
330 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
331 return new FileFetcher();
332 }
333
334 // Necessary to unhide the definition in the base class.
335 using AnyHttpFetcherTest::NewSmallFetcher;
336 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
337 return NewLargeFetcher(proxy_resolver);
338 }
339
340 string BigUrl(in_port_t port) const override {
Tao Bao642b32b2019-01-02 15:33:42 -0800341 static string big_contents = []() {
342 string buf;
343 buf.reserve(kBigLength);
344 constexpr const char* kBigUrlContent = "abcdefghij";
345 for (size_t i = 0; i < kBigLength; i += strlen(kBigUrlContent)) {
346 buf.append(kBigUrlContent,
347 std::min(kBigLength - i, strlen(kBigUrlContent)));
348 }
349 return buf;
350 }();
351 test_utils::WriteFileString(temp_file_.path(), big_contents);
Alex Deymo2c131bb2016-05-26 16:43:13 -0700352 return "file://" + temp_file_.path();
353 }
354 string SmallUrl(in_port_t port) const override {
355 test_utils::WriteFileString(temp_file_.path(), "small contents");
356 return "file://" + temp_file_.path();
357 }
358 string ErrorUrl(in_port_t port) const override {
359 return "file:///path/to/non-existing-file";
360 }
361
362 bool IsMock() const override { return false; }
363 bool IsMulti() const override { return false; }
364 bool IsHttpSupported() const override { return false; }
Tao Bao642b32b2019-01-02 15:33:42 -0800365 bool IsFileFetcher() const override { return true; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700366
367 void IgnoreServerAborting(HttpServer* server) const override {}
368
369 HttpServer* CreateServer() override { return new NullHttpServer; }
370
371 private:
Amin Hassanied03b442020-10-26 17:21:29 -0700372 ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
Alex Deymo2c131bb2016-05-26 16:43:13 -0700373};
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800374
Tao Bao642b32b2019-01-02 15:33:42 -0800375class MultiRangeHttpFetcherOverFileFetcherTest : public FileFetcherTest {
376 public:
377 // Necessary to unhide the definition in the base class.
378 using AnyHttpFetcherTest::NewLargeFetcher;
379 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
380 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(new FileFetcher());
381 ret->ClearRanges();
382 // FileFetcher doesn't support range with unspecified length.
383 ret->AddRange(0, 1);
384 // Speed up test execution.
385 ret->set_idle_seconds(1);
386 ret->set_retry_seconds(1);
387 fake_hardware_.SetIsOfficialBuild(false);
388 return ret;
389 }
390
391 // Necessary to unhide the definition in the base class.
392 using AnyHttpFetcherTest::NewSmallFetcher;
393 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
394 return NewLargeFetcher(proxy_resolver);
395 }
396
397 bool IsMulti() const override { return true; }
398};
399
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800400//
401// Infrastructure for type tests of HTTP fetcher.
402// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
403//
404
405// Fixture class template. We use an explicit constraint to guarantee that it
406// can only be instantiated with an AnyHttpFetcherTest type, see:
407// http://www2.research.att.com/~bs/bs_faq2.html#constraints
408template <typename T>
409class HttpFetcherTest : public ::testing::Test {
410 public:
Qijiang Fanb0b6cc22020-10-15 21:54:11 +0900411#if BASE_VER < 780000 // Android
Alex Deymo535f3b72015-08-07 10:51:32 -0700412 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700413 brillo::BaseMessageLoop loop_{&base_loop_};
Qijiang Fanb0b6cc22020-10-15 21:54:11 +0900414#else // Chrome OS
415 base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
416 brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
417#endif // BASE_VER < 780000
Alex Deymo60ca1a72015-06-18 18:19:15 -0700418
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800419 T test_;
420
Alex Deymo60ca1a72015-06-18 18:19:15 -0700421 protected:
Amin Hassanib2689592019-01-13 17:04:28 -0800422 HttpFetcherTest() { loop_.SetAsCurrent(); }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700423
424 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700425 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700426 }
427
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800428 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700429 static void TypeConstraint(T* a) {
Amin Hassanib2689592019-01-13 17:04:28 -0800430 AnyHttpFetcherTest* b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700431 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700432 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800433 }
434};
435
436// Test case types list.
437typedef ::testing::Types<LibcurlHttpFetcherTest,
438 MockHttpFetcherTest,
Alex Deymo2c131bb2016-05-26 16:43:13 -0700439 MultiRangeHttpFetcherTest,
Tao Bao642b32b2019-01-02 15:33:42 -0800440 FileFetcherTest,
441 MultiRangeHttpFetcherOverFileFetcherTest>
Alex Deymo2c131bb2016-05-26 16:43:13 -0700442 HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000443TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
444
445namespace {
446class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000447 public:
Alex Deymofdd6dec2016-03-03 22:35:43 -0800448 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800449
Amin Hassani0cd9d772018-07-31 23:55:43 -0700450 bool ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymofdd6dec2016-03-03 22:35:43 -0800451 const void* bytes,
452 size_t length) override {
453 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800454 // Update counters
455 times_received_bytes_called_++;
Amin Hassani0cd9d772018-07-31 23:55:43 -0700456 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000457 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800458
Alex Deymo610277e2014-11-11 21:18:11 -0800459 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800460 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800461 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800462 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800463 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700464 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800465
466 // Update counter
467 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000468 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800469
Alex Deymo610277e2014-11-11 21:18:11 -0800470 void TransferTerminated(HttpFetcher* fetcher) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800471 times_transfer_terminated_called_++;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700472 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800473 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800474
Gilad Arnold48085ba2011-11-16 09:36:08 -0800475 // Are we expecting an error response? (default: no)
Alex Deymofdd6dec2016-03-03 22:35:43 -0800476 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800477
478 // Counters for callback invocations.
Alex Deymofdd6dec2016-03-03 22:35:43 -0800479 int times_transfer_complete_called_{0};
480 int times_transfer_terminated_called_{0};
481 int times_received_bytes_called_{0};
482
483 // The received data bytes.
484 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000485};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000486
Alex Deymo60ca1a72015-06-18 18:19:15 -0700487void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
488 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000489}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700490} // namespace
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 +0000595namespace {
596class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
597 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700598 bool ReceivedBytes(HttpFetcher* fetcher,
599 const void* /* bytes */,
600 size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000601 CHECK(!paused_);
602 paused_ = true;
603 fetcher->Pause();
Amin Hassani0cd9d772018-07-31 23:55:43 -0700604 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000605 }
Alex Deymo610277e2014-11-11 21:18:11 -0800606 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700607 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000608 }
Amin Hassanib2689592019-01-13 17:04:28 -0800609 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000610 void Unpause() {
611 CHECK(paused_);
612 paused_ = false;
613 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000614 }
615 bool paused_;
616 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000617};
618
Alex Deymo60ca1a72015-06-18 18:19:15 -0700619void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
620 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000621 if (delegate->paused_)
622 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700623 // Update the task id with the new scheduled callback.
624 *my_id = MessageLoop::current()->PostDelayedTask(
625 FROM_HERE,
626 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
627 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000628}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700629} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000630
631TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800632 PausingHttpFetcherTestDelegate delegate;
633 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
634 delegate.paused_ = false;
635 delegate.fetcher_ = fetcher.get();
636 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000637
Alex Deymof2858572016-02-25 11:20:13 -0800638 unique_ptr<HttpServer> server(this->test_.CreateServer());
639 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800640
Alex Deymof2858572016-02-25 11:20:13 -0800641 MessageLoop::TaskId callback_id;
642 callback_id = this->loop_.PostDelayedTask(
643 FROM_HERE,
644 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
645 base::TimeDelta::FromMilliseconds(200));
646 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000647
Alex Deymof2858572016-02-25 11:20:13 -0800648 this->loop_.Run();
649 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
650}
651
652// This test will pause the fetcher while the download is not yet started
653// because it is waiting for the proxy to be resolved.
654TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700655 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymof2858572016-02-25 11:20:13 -0800656 return;
657 MockProxyResolver mock_resolver;
658 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
659
660 // Saved arguments from the proxy call.
Alex Deymo35821942017-02-05 04:36:02 +0000661 ProxiesResolvedFn proxy_callback;
662 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _))
663 .WillOnce(DoAll(SaveArg<1>(&proxy_callback), Return(true)));
Alex Deymof2858572016-02-25 11:20:13 -0800664 fetcher->BeginTransfer("http://fake_url");
665 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
666
667 // Pausing and unpausing while resolving the proxy should not affect anything.
668 fetcher->Pause();
669 fetcher->Unpause();
670 fetcher->Pause();
671 // Proxy resolver comes back after we paused the fetcher.
Alex Deymoc00ec562017-02-05 04:36:02 +0000672 ASSERT_FALSE(proxy_callback.is_null());
Alex Deymo35821942017-02-05 04:36:02 +0000673 proxy_callback.Run({1, kNoProxy});
rspangler@google.com49fdf182009-10-10 00:57:34 +0000674}
675
676namespace {
677class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
678 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700679 bool ReceivedBytes(HttpFetcher* fetcher,
680 const void* bytes,
681 size_t length) override {
682 return true;
683 }
Alex Deymo610277e2014-11-11 21:18:11 -0800684 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800685 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700686 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000687 }
Alex Deymo610277e2014-11-11 21:18:11 -0800688 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800689 EXPECT_EQ(fetcher, fetcher_.get());
690 EXPECT_FALSE(once_);
691 EXPECT_TRUE(callback_once_);
692 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700693 // The fetcher could have a callback scheduled on the ProxyResolver that
694 // can fire after this callback. We wait until the end of the test to
695 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800696 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000697 void TerminateTransfer() {
698 CHECK(once_);
699 once_ = false;
700 fetcher_->TerminateTransfer();
701 }
Amin Hassanib2689592019-01-13 17:04:28 -0800702 void EndLoop() { MessageLoop::current()->BreakLoop(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000703 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800704 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700705 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000706};
707
Alex Deymo60ca1a72015-06-18 18:19:15 -0700708void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
709 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000710 if (delegate->once_) {
711 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700712 *my_id = MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800713 FROM_HERE, base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000714 } else {
715 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700716 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000717 }
718}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700719} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000720
721TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700722 AbortingHttpFetcherTestDelegate delegate;
723 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
724 delegate.once_ = true;
725 delegate.callback_once_ = true;
726 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000727
Alex Deymo60ca1a72015-06-18 18:19:15 -0700728 unique_ptr<HttpServer> server(this->test_.CreateServer());
729 this->test_.IgnoreServerAborting(server.get());
730 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800731
Alex Deymo60ca1a72015-06-18 18:19:15 -0700732 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000733
Alex Deymo60ca1a72015-06-18 18:19:15 -0700734 task_id = this->loop_.PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800735 FROM_HERE, base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700736 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
737
738 this->loop_.Run();
739 CHECK(!delegate.once_);
740 CHECK(!delegate.callback_once_);
741 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000742}
743
Alex Deymo71f67622017-02-03 21:30:24 -0800744TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
745 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
746 return;
747 MockProxyResolver mock_resolver;
748 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
749
750 HttpFetcherTestDelegate delegate;
751 fetcher->set_delegate(&delegate);
752
753 EXPECT_CALL(mock_resolver, GetProxiesForUrl(_, _)).WillOnce(Return(123));
754 fetcher->BeginTransfer("http://fake_url");
755 // Run the message loop until idle. This must call the MockProxyResolver with
756 // the request.
757 while (this->loop_.RunOnce(false)) {
758 }
759 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
760
761 EXPECT_CALL(mock_resolver, CancelProxyRequest(123)).WillOnce(Return(true));
762
763 // Terminate the transfer right before the proxy resolution response.
764 fetcher->TerminateTransfer();
765 EXPECT_EQ(0, delegate.times_received_bytes_called_);
766 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
767 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
768}
769
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000770namespace {
771class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
772 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700773 bool ReceivedBytes(HttpFetcher* fetcher,
774 const void* bytes,
775 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800776 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700777 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000778 }
Alex Deymo610277e2014-11-11 21:18:11 -0800779 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700780 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800781 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700782 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000783 }
Amin Hassanib2689592019-01-13 17:04:28 -0800784 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000785 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000786};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700787} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000788
789TYPED_TEST(HttpFetcherTest, FlakyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700790 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000791 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000792 {
793 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700794 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000795 fetcher->set_delegate(&delegate);
796
Ben Chan02f7c1d2014-10-18 15:18:02 -0700797 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800798 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000799
Amin Hassanib2689592019-01-13 17:04:28 -0800800 this->loop_.PostTask(FROM_HERE,
801 base::Bind(&StartTransfer,
802 fetcher.get(),
803 LocalServerUrlForPath(
804 server->GetPort(),
805 base::StringPrintf("/flaky/%d/%d/%d/%d",
806 kBigLength,
807 kFlakyTruncateLength,
808 kFlakySleepEvery,
809 kFlakySleepSecs))));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700810 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000811
812 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800813 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800814 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000815 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
816 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
817 }
818 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000819}
820
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700821namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700822// This delegate kills the server attached to it after receiving any bytes.
823// This can be used for testing what happens when you try to fetch data and
824// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700825class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
826 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700827 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700828 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700829
Alex Deymo610277e2014-11-11 21:18:11 -0800830 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700831 if (server_) {
832 LOG(INFO) << "Stopping server in destructor";
Alex Deymob20de692017-02-05 07:47:37 +0000833 server_.reset();
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700834 LOG(INFO) << "server stopped";
835 }
836 }
837
Amin Hassani0cd9d772018-07-31 23:55:43 -0700838 bool ReceivedBytes(HttpFetcher* fetcher,
839 const void* bytes,
840 size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700841 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700842 LOG(INFO) << "Stopping server in ReceivedBytes";
Alex Deymob20de692017-02-05 07:47:37 +0000843 server_.reset();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700844 LOG(INFO) << "server stopped";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700845 }
Amin Hassani0cd9d772018-07-31 23:55:43 -0700846 return true;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700847 }
Alex Deymo610277e2014-11-11 21:18:11 -0800848 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700849 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700850 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymob20de692017-02-05 07:47:37 +0000851 times_transfer_complete_called_++;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700852 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700853 }
Alex Deymo610277e2014-11-11 21:18:11 -0800854 void TransferTerminated(HttpFetcher* fetcher) override {
Alex Deymob20de692017-02-05 07:47:37 +0000855 times_transfer_terminated_called_++;
856 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800857 }
Alex Deymob20de692017-02-05 07:47:37 +0000858 unique_ptr<PythonHttpServer> server_;
859 int times_transfer_terminated_called_{0};
860 int times_transfer_complete_called_{0};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700861};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700862} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700863
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700864TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700865 // This test ensures that a fetcher responds correctly when a server isn't
866 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800867 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700868 return;
Alex Deymob20de692017-02-05 07:47:37 +0000869 FailureHttpFetcherTestDelegate delegate(nullptr);
870 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
871 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700872
Alex Deymob20de692017-02-05 07:47:37 +0000873 this->loop_.PostTask(
874 FROM_HERE,
875 base::Bind(
876 StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
877 this->loop_.Run();
878 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
879 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700880
Alex Deymob20de692017-02-05 07:47:37 +0000881 // Exiting and testing happens in the delegate
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700882}
883
Alex Deymof123ae22015-09-24 14:59:43 -0700884TYPED_TEST(HttpFetcherTest, NoResponseTest) {
885 // This test starts a new http server but the server doesn't respond and just
886 // closes the connection.
887 if (this->test_.IsMock())
888 return;
889
890 PythonHttpServer* server = new PythonHttpServer();
891 int port = server->GetPort();
892 ASSERT_TRUE(server->started_);
893
894 // Handles destruction and claims ownership.
895 FailureHttpFetcherTestDelegate delegate(server);
896 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
897 fetcher->set_delegate(&delegate);
898 // The server will not reply at all, so we can limit the execution time of the
899 // test by reducing the low-speed timeout to something small. The test will
900 // finish once the TimeoutCallback() triggers (every second) and the timeout
901 // expired.
902 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
903
Amin Hassanib2689592019-01-13 17:04:28 -0800904 this->loop_.PostTask(
905 FROM_HERE,
906 base::Bind(
907 StartTransfer, fetcher.get(), LocalServerUrlForPath(port, "/hang")));
Alex Deymof123ae22015-09-24 14:59:43 -0700908 this->loop_.Run();
Alex Deymob20de692017-02-05 07:47:37 +0000909 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
910 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Alex Deymof123ae22015-09-24 14:59:43 -0700911
912 // Check that no other callback runs in the next two seconds. That would
913 // indicate a leaked callback.
914 bool timeout = false;
Luis Hector Chavezf1cf3482016-07-19 14:29:19 -0700915 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
916 base::Unretained(&timeout));
Amin Hassanib2689592019-01-13 17:04:28 -0800917 this->loop_.PostDelayedTask(
918 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
Alex Deymof123ae22015-09-24 14:59:43 -0700919 EXPECT_TRUE(this->loop_.RunOnce(true));
920 EXPECT_TRUE(timeout);
921}
922
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700923TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700924 // This test starts a new http server and kills it after receiving its first
925 // set of bytes. It test whether or not our fetcher eventually gives up on
926 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800927 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700928 return;
Alex Deymob20de692017-02-05 07:47:37 +0000929 PythonHttpServer* server = new PythonHttpServer();
930 int port = server->GetPort();
931 ASSERT_TRUE(server->started_);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700932
Alex Deymob20de692017-02-05 07:47:37 +0000933 // Handles destruction and claims ownership.
934 FailureHttpFetcherTestDelegate delegate(server);
935 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
936 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700937
Alex Deymob20de692017-02-05 07:47:37 +0000938 this->loop_.PostTask(
939 FROM_HERE,
940 base::Bind(StartTransfer,
941 fetcher.get(),
942 LocalServerUrlForPath(port,
943 base::StringPrintf("/flaky/%d/%d/%d/%d",
944 kBigLength,
945 kFlakyTruncateLength,
946 kFlakySleepEvery,
947 kFlakySleepSecs))));
948 this->loop_.Run();
949 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
950 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700951
Alex Deymob20de692017-02-05 07:47:37 +0000952 // Exiting and testing happens in the delegate
953}
954
955// Test that we can cancel a transfer while it is still trying to connect to the
956// server. This test kills the server after a few bytes are received.
957TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
958 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
959 return;
960
961 PythonHttpServer* server = new PythonHttpServer();
962 int port = server->GetPort();
963 ASSERT_TRUE(server->started_);
964
965 // Handles destruction and claims ownership.
966 FailureHttpFetcherTestDelegate delegate(server);
967 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
968 fetcher->set_delegate(&delegate);
969
970 this->loop_.PostTask(
971 FROM_HERE,
972 base::Bind(StartTransfer,
973 fetcher.get(),
974 LocalServerUrlForPath(port,
975 base::StringPrintf("/flaky/%d/%d/%d/%d",
976 kBigLength,
977 kFlakyTruncateLength,
978 kFlakySleepEvery,
979 kFlakySleepSecs))));
980 // Terminating the transfer after 3 seconds gives it a chance to contact the
981 // server and enter the retry loop.
982 this->loop_.PostDelayedTask(FROM_HERE,
983 base::Bind(&HttpFetcher::TerminateTransfer,
984 base::Unretained(fetcher.get())),
985 base::TimeDelta::FromSeconds(3));
986
987 // Exiting and testing happens in the delegate.
988 this->loop_.Run();
989 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
990 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
991
992 // Check that no other callback runs in the next two seconds. That would
993 // indicate a leaked callback.
994 bool timeout = false;
995 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
996 base::Unretained(&timeout));
997 this->loop_.PostDelayedTask(
998 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
999 EXPECT_TRUE(this->loop_.RunOnce(true));
1000 EXPECT_TRUE(timeout);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -07001001}
1002
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001003namespace {
Amin Hassanib2689592019-01-13 17:04:28 -08001004const HttpResponseCode kRedirectCodes[] = {kHttpResponseMovedPermanently,
1005 kHttpResponseFound,
1006 kHttpResponseSeeOther,
1007 kHttpResponseTempRedirect};
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001008
1009class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
1010 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001011 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001012 : expected_successful_(expected_successful) {}
Amin Hassani0cd9d772018-07-31 23:55:43 -07001013 bool ReceivedBytes(HttpFetcher* fetcher,
1014 const void* bytes,
1015 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001016 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001017 return true;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001018 }
Alex Deymo610277e2014-11-11 21:18:11 -08001019 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001020 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001021 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001022 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001023 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001024 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
1025 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -07001026 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001027 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001028 }
Amin Hassanib2689592019-01-13 17:04:28 -08001029 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001030 bool expected_successful_;
1031 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001032};
1033
1034// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001035void RedirectTest(const HttpServer* server,
1036 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001037 const string& url,
1038 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001039 RedirectHttpFetcherTestDelegate delegate(expected_successful);
1040 unique_ptr<HttpFetcher> fetcher(http_fetcher);
1041 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001042
Amin Hassanib2689592019-01-13 17:04:28 -08001043 MessageLoop::current()->PostTask(
1044 FROM_HERE,
1045 base::Bind(StartTransfer,
1046 fetcher.get(),
1047 LocalServerUrlForPath(server->GetPort(), url)));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001048 MessageLoop::current()->Run();
1049 if (expected_successful) {
1050 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -08001051 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -07001052 for (int i = 0; i < kMediumLength; i += 10) {
1053 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
1054 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001055 }
1056 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001057}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001058} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001059
1060TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001061 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001062 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001063
Ben Chan02f7c1d2014-10-18 15:18:02 -07001064 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001065 ASSERT_TRUE(server->started_);
1066
hscham00b6aa22020-02-20 12:32:06 +09001067 for (size_t c = 0; c < base::size(kRedirectCodes); ++c) {
Amin Hassanib2689592019-01-13 17:04:28 -08001068 const string url = base::StringPrintf(
1069 "/redirect/%d/download/%d", kRedirectCodes[c], kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001070 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001071 }
1072}
1073
1074TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001075 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001076 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001077
Ben Chan02f7c1d2014-10-18 15:18:02 -07001078 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001079 ASSERT_TRUE(server->started_);
1080
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001081 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001082 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001083 url += base::StringPrintf("/redirect/%d",
hscham00b6aa22020-02-20 12:32:06 +09001084 kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001085 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001086 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001087 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001088}
1089
1090TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001091 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001092 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001093
Ben Chan02f7c1d2014-10-18 15:18:02 -07001094 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001095 ASSERT_TRUE(server->started_);
1096
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001097 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001098 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001099 url += base::StringPrintf("/redirect/%d",
hscham00b6aa22020-02-20 12:32:06 +09001100 kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001101 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001102 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001103 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001104}
1105
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001106namespace {
1107class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1108 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001109 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001110 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001111
Amin Hassani0cd9d772018-07-31 23:55:43 -07001112 bool ReceivedBytes(HttpFetcher* fetcher,
1113 const void* bytes,
1114 size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001115 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001116 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001117 return true;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001118 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001119
Alex Deymo610277e2014-11-11 21:18:11 -08001120 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001121 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001122 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001123 if (expected_response_code_ != 0)
1124 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001125 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -07001126 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001127 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001128 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001129
Amin Hassanib2689592019-01-13 17:04:28 -08001130 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001131
Ben Chan02f7c1d2014-10-18 15:18:02 -07001132 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001133 int expected_response_code_;
1134 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001135};
1136
1137void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -03001138 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001139 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -07001140 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001141 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -08001142 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001143 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001144 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1145 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001146
Alex Deymo60ca1a72015-06-18 18:19:15 -07001147 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -08001148 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001149 ASSERT_TRUE(multi_fetcher);
1150 multi_fetcher->ClearRanges();
1151 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
Amin Hassanib2689592019-01-13 17:04:28 -08001152 e = ranges.end();
1153 it != e;
1154 ++it) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001155 string tmp_str = base::StringPrintf("%jd+", it->first);
1156 if (it->second > 0) {
1157 base::StringAppendF(&tmp_str, "%jd", it->second);
1158 multi_fetcher->AddRange(it->first, it->second);
1159 } else {
1160 base::StringAppendF(&tmp_str, "?");
1161 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001162 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001163 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001164 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001165 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001166 multi_fetcher->set_delegate(&delegate);
1167
1168 MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -08001169 FROM_HERE, base::Bind(StartTransfer, multi_fetcher, url));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001170 MessageLoop::current()->Run();
1171
1172 EXPECT_EQ(expected_size, delegate.data.size());
1173 EXPECT_EQ(expected_prefix,
1174 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001175}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001176} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001177
Darin Petkov9ce452b2010-11-17 14:33:28 -08001178TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001179 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001180 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001181
Ben Chan02f7c1d2014-10-18 15:18:02 -07001182 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001183 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001184
Ben Chanf9cb98c2014-09-21 18:31:30 -07001185 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001186 ranges.push_back(make_pair(0, 25));
Tao Bao642b32b2019-01-02 15:33:42 -08001187 ranges.push_back(make_pair(99, 17));
1188 MultiTest(this->test_.NewLargeFetcher(),
1189 this->test_.fake_hardware(),
1190 this->test_.BigUrl(server->GetPort()),
1191 ranges,
1192 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1193 25 + 17,
1194 this->test_.IsFileFetcher() ? kHttpResponseOk
1195 : kHttpResponsePartialContent);
1196}
1197
1198TYPED_TEST(HttpFetcherTest, MultiHttpFetcherUnspecifiedEndTest) {
1199 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1200 return;
1201
1202 unique_ptr<HttpServer> server(this->test_.CreateServer());
1203 ASSERT_TRUE(server->started_);
1204
1205 vector<pair<off_t, off_t>> ranges;
1206 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001207 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001208 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001209 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001210 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001211 ranges,
1212 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001213 kBigLength - (99 - 25),
1214 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001215}
1216
1217TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001218 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001219 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001220
Ben Chan02f7c1d2014-10-18 15:18:02 -07001221 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001222 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001223
Ben Chanf9cb98c2014-09-21 18:31:30 -07001224 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001225 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001226 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001227 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001228 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001229 ranges,
1230 "abcdefghijabcdefghijabcd",
1231 24,
Tao Bao642b32b2019-01-02 15:33:42 -08001232 this->test_.IsFileFetcher() ? kHttpResponseOk
1233 : kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001234}
1235
1236TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001237 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001238 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001239
Ben Chan02f7c1d2014-10-18 15:18:02 -07001240 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001241 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001242
Ben Chanf9cb98c2014-09-21 18:31:30 -07001243 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001244 ranges.push_back(make_pair(kBigLength - 2, 0));
1245 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001246 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001247 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001248 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001249 ranges,
1250 "ijhij",
1251 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001252 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001253}
1254
1255TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001256 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001257 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001258
Ben Chan02f7c1d2014-10-18 15:18:02 -07001259 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001260 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001261
Ben Chanf9cb98c2014-09-21 18:31:30 -07001262 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001263 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001264 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001265 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001266 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001267 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001268 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001269 ranges,
1270 "ij",
1271 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001272 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001273 ranges.push_back(make_pair(0, 5));
1274 }
1275}
1276
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001277// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1278// should retry with other proxies listed before giving up.
1279//
1280// (1) successful recovery: The offset fetch will fail twice but succeed with
1281// the third proxy.
1282TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001283 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001284 return;
1285
Ben Chan02f7c1d2014-10-18 15:18:02 -07001286 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001287 ASSERT_TRUE(server->started_);
1288
Ben Chanf9cb98c2014-09-21 18:31:30 -07001289 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001290 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001291 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001292 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001293 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001294 LocalServerUrlForPath(
1295 server->GetPort(),
1296 base::StringPrintf("/error-if-offset/%d/2", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001297 ranges,
1298 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1299 kBigLength - (99 - 25),
1300 kHttpResponsePartialContent);
1301}
1302
1303// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1304// fetcher will signal a (failed) completed transfer to the delegate.
1305TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001306 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001307 return;
1308
Ben Chan02f7c1d2014-10-18 15:18:02 -07001309 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001310 ASSERT_TRUE(server->started_);
1311
Ben Chanf9cb98c2014-09-21 18:31:30 -07001312 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001313 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001314 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001315 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001316 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001317 LocalServerUrlForPath(
1318 server->GetPort(),
1319 base::StringPrintf("/error-if-offset/%d/3", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001320 ranges,
1321 "abcdefghijabcdefghijabcde", // only received the first chunk
1322 25,
1323 kHttpResponseUndefined);
1324}
1325
Alex Deymo4ea2d922017-02-05 07:35:32 +00001326namespace {
1327// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1328class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1329 public:
1330 explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1331 : terminate_trigger_bytes_(terminate_trigger_bytes) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001332
Amin Hassani0cd9d772018-07-31 23:55:43 -07001333 bool ReceivedBytes(HttpFetcher* fetcher,
Alex Deymo4ea2d922017-02-05 07:35:32 +00001334 const void* bytes,
1335 size_t length) override {
1336 LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
1337 EXPECT_EQ(fetcher, fetcher_.get());
Tao Bao642b32b2019-01-02 15:33:42 -08001338 bool should_terminate = false;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001339 if (bytes_downloaded_ < terminate_trigger_bytes_ &&
1340 bytes_downloaded_ + length >= terminate_trigger_bytes_) {
1341 MessageLoop::current()->PostTask(
1342 FROM_HERE,
1343 base::Bind(&HttpFetcher::TerminateTransfer,
1344 base::Unretained(fetcher_.get())));
Tao Bao642b32b2019-01-02 15:33:42 -08001345 should_terminate = true;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001346 }
1347 bytes_downloaded_ += length;
Tao Bao642b32b2019-01-02 15:33:42 -08001348 return !should_terminate;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001349 }
1350
1351 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1352 ADD_FAILURE() << "TransferComplete called but expected a failure";
1353 // Destroy the fetcher (because we're allowed to).
1354 fetcher_.reset(nullptr);
1355 MessageLoop::current()->BreakLoop();
1356 }
1357
1358 void TransferTerminated(HttpFetcher* fetcher) override {
1359 // Destroy the fetcher (because we're allowed to).
1360 fetcher_.reset(nullptr);
1361 MessageLoop::current()->BreakLoop();
1362 }
1363
1364 unique_ptr<HttpFetcher> fetcher_;
1365 size_t bytes_downloaded_{0};
1366 size_t terminate_trigger_bytes_;
1367};
1368} // namespace
1369
1370TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
1371 if (!this->test_.IsMulti())
1372 return;
1373 const size_t kRangeTrigger = 1000;
1374 MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
1375
1376 unique_ptr<HttpServer> server(this->test_.CreateServer());
1377 ASSERT_TRUE(server->started_);
1378
1379 MultiRangeHttpFetcher* multi_fetcher =
1380 static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
1381 ASSERT_TRUE(multi_fetcher);
1382 // Transfer ownership of the fetcher to the delegate.
1383 delegate.fetcher_.reset(multi_fetcher);
1384 multi_fetcher->set_delegate(&delegate);
1385
1386 multi_fetcher->ClearRanges();
1387 multi_fetcher->AddRange(45, kRangeTrigger);
1388 multi_fetcher->AddRange(2000, 100);
1389
1390 this->test_.fake_hardware()->SetIsOfficialBuild(false);
1391
1392 StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
1393 MessageLoop::current()->Run();
1394
1395 // Check that the delegate made it to the trigger point.
1396 EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
1397}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001398
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001399namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001400class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001401 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -07001402 bool ReceivedBytes(HttpFetcher* fetcher,
1403 const void* bytes,
1404 size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001405 ADD_FAILURE();
Amin Hassani0cd9d772018-07-31 23:55:43 -07001406 return true;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001407 }
Alex Deymo610277e2014-11-11 21:18:11 -08001408 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001409 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001410 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001411 }
Amin Hassanib2689592019-01-13 17:04:28 -08001412 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001413};
1414
Alex Deymo60ca1a72015-06-18 18:19:15 -07001415void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1416 bool is_official_build) {
1417 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1418 return;
1419
1420 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1421 ASSERT_TRUE(server->started_);
1422
1423 BlockedTransferTestDelegate delegate;
1424 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1425 LOG(INFO) << "is_official_build: " << is_official_build;
1426 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001427 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001428 fetcher->set_delegate(&delegate);
1429
Amin Hassanib2689592019-01-13 17:04:28 -08001430 MessageLoop::current()->PostTask(
1431 FROM_HERE,
1432 base::Bind(
1433 StartTransfer,
1434 fetcher.get(),
1435 LocalServerUrlForPath(server->GetPort(),
1436 fetcher_test->SmallUrl(server->GetPort()))));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001437 MessageLoop::current()->Run();
1438}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001439} // namespace
1440
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001441TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001442 BlockedTransferTestHelper(&this->test_, false);
1443}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001444
Alex Deymo60ca1a72015-06-18 18:19:15 -07001445TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1446 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001447}
1448
rspangler@google.com49fdf182009-10-10 00:57:34 +00001449} // namespace chromeos_update_engine