blob: 7821f4c4d1a95e7d1e591df7db011712fb7d152a [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>
Daniel Zheng3e881aa2022-09-07 22:10:29 +000023#include <deque>
Ben Chan02f7c1d2014-10-18 15:18:02 -070024#include <memory>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000025#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070026#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000027#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070028
Kokoa Matsuda11c3da62024-10-23 13:40:44 +090029#include <android-base/stringprintf.h>
Alex Deymo706a5ab2015-11-23 17:48:30 -030030#include <base/bind.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070031#include <base/location.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080032#include <base/logging.h>
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090033#if BASE_VER < 780000 // Android
Alex Deymo535f3b72015-08-07 10:51:32 -070034#include <base/message_loop/message_loop.h>
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090035#endif // BASE_VER < 780000
hscham00b6aa22020-02-20 12:32:06 +090036#include <base/stl_util.h>
Alex Deymo535f3b72015-08-07 10:51:32 -070037#include <base/strings/string_number_conversions.h>
Kelvin Zhang0c184242024-10-25 11:19:27 -070038#include <android-base/stringprintf.h>
Qijiang Fanb0b6cc22020-10-15 21:54:11 +090039#if BASE_VER >= 780000 // CrOS
40#include <base/task/single_thread_task_executor.h>
41#endif // BASE_VER >= 780000
Alex Vakulenko75039d72014-03-25 12:36:28 -070042#include <base/time/time.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070043#include <brillo/message_loops/base_message_loop.h>
44#include <brillo/message_loops/message_loop.h>
45#include <brillo/message_loops/message_loop_utils.h>
Amin Hassani4bd46b32020-09-15 15:30:09 -070046#ifdef __CHROMEOS__
47#include <brillo/process/process.h>
48#else
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070049#include <brillo/process.h>
Amin Hassani4bd46b32020-09-15 15:30:09 -070050#endif // __CHROMEOS__
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070051#include <brillo/streams/file_stream.h>
52#include <brillo/streams/stream.h>
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -070053#include <gmock/gmock.h>
Daniel Zheng3e881aa2022-09-07 22:10:29 +000054#include <gtest/gtest.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080055
Alex Deymoc1c17b42015-11-23 03:53:15 -030056#include "update_engine/common/fake_hardware.h"
Alex Deymo2c131bb2016-05-26 16:43:13 -070057#include "update_engine/common/file_fetcher.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080058#include "update_engine/common/http_common.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080059#include "update_engine/common/mock_http_fetcher.h"
60#include "update_engine/common/multi_range_http_fetcher.h"
61#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) {
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -070091 string port_str = (port ? android::base::StringPrintf(":%hu", port) : "");
92 return android::base::StringPrintf(
Amin Hassanib2689592019-01-13 17:04:28 -080093 "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) {
Daniel Zheng3e881aa2022-09-07 22:10:29 +0000144 size_t read{};
Alex Deymo535f3b72015-08-07 10:51:32 -0700145 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
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700203 virtual HttpFetcher* NewLargeFetcher() = 0;
Alex Deymof2858572016-02-25 11:20:13 -0800204 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700205 auto res = NewLargeFetcher();
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800206
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700207 res->SetProxies(std::deque<std::string>(num_proxies, kNoProxy));
208 return res;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800209 }
210
Daniel Zheng3e881aa2022-09-07 22:10:29 +0000211 virtual HttpFetcher* NewSmallFetcher() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800212
Daniel Zheng3e881aa2022-09-07 22:10:29 +0000213 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
214 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
215 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800216
Daniel Zheng3e881aa2022-09-07 22:10:29 +0000217 virtual bool IsMock() const = 0;
218 virtual bool IsMulti() const = 0;
219 virtual bool IsHttpSupported() const = 0;
220 virtual bool IsFileFetcher() const = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800221
Daniel Zheng3e881aa2022-09-07 22:10:29 +0000222 virtual void IgnoreServerAborting(HttpServer* server) const {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800223
Daniel Zheng3e881aa2022-09-07 22:10:29 +0000224 virtual HttpServer* CreateServer() = 0;
Alex Deymoc1c17b42015-11-23 03:53:15 -0300225
Daniel Zheng3e881aa2022-09-07 22:10:29 +0000226 FakeHardware* fake_hardware() { return &fake_hardware_; }
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700227
Daniel Zheng3e881aa2022-09-07 22:10:29 +0000228 protected:
229 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800230};
231
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700232class MockHttpFetcherFactory : public AnyHttpFetcherFactory {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800233 public:
234 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700235 using AnyHttpFetcherFactory::NewLargeFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700236 HttpFetcher* NewLargeFetcher() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700237 brillo::Blob big_data(1000000);
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700238 return new MockHttpFetcher(big_data.data(), big_data.size());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800239 }
240
241 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700242 using AnyHttpFetcherFactory::NewSmallFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700243 HttpFetcher* NewSmallFetcher() override {
244 return new MockHttpFetcher("x", 1);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800245 }
246
Alex Deymo610277e2014-11-11 21:18:11 -0800247 bool IsMock() const override { return true; }
248 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700249 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800250 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800251
Amin Hassanib2689592019-01-13 17:04:28 -0800252 HttpServer* CreateServer() override { return new NullHttpServer; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800253};
254
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700255class LibcurlHttpFetcherFactory : public AnyHttpFetcherFactory {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800256 public:
257 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700258 using AnyHttpFetcherFactory::NewLargeFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700259 HttpFetcher* NewLargeFetcher() override {
260 LibcurlHttpFetcher* ret = new LibcurlHttpFetcher(&fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700261 // Speed up test execution.
262 ret->set_idle_seconds(1);
263 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300264 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000265 return ret;
266 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800267
268 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700269 using AnyHttpFetcherFactory::NewSmallFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700270
271 HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800272
Alex Deymo610277e2014-11-11 21:18:11 -0800273 string BigUrl(in_port_t port) const override {
Amin Hassanib2689592019-01-13 17:04:28 -0800274 return LocalServerUrlForPath(
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -0700275 port, android::base::StringPrintf("/download/%d", kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000276 }
Alex Deymo610277e2014-11-11 21:18:11 -0800277 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700278 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000279 }
Alex Deymo610277e2014-11-11 21:18:11 -0800280 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700281 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800282 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800283
Alex Deymo610277e2014-11-11 21:18:11 -0800284 bool IsMock() const override { return false; }
285 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700286 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800287 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800288
Alex Deymo610277e2014-11-11 21:18:11 -0800289 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700290 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700291 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800292
Amin Hassanib2689592019-01-13 17:04:28 -0800293 HttpServer* CreateServer() override { return new PythonHttpServer; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000294};
295
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700296class MultiRangeHttpFetcherFactory : public LibcurlHttpFetcherFactory {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700297 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800298 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700299 using AnyHttpFetcherFactory::NewLargeFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700300 HttpFetcher* NewLargeFetcher() override {
301 MultiRangeHttpFetcher* ret =
302 new MultiRangeHttpFetcher(new LibcurlHttpFetcher(&fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800303 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800304 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700305 // Speed up test execution.
306 ret->set_idle_seconds(1);
307 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300308 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700309 return ret;
310 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800311
312 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700313 using AnyHttpFetcherFactory::NewSmallFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700314 HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800315
Alex Deymo610277e2014-11-11 21:18:11 -0800316 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700317};
318
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700319class FileFetcherFactory : public AnyHttpFetcherFactory {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700320 public:
321 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700322 using AnyHttpFetcherFactory::NewLargeFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700323 HttpFetcher* NewLargeFetcher() override { return new FileFetcher(); }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700324
325 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700326 using AnyHttpFetcherFactory::NewSmallFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700327 HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700328
329 string BigUrl(in_port_t port) const override {
Tao Bao642b32b2019-01-02 15:33:42 -0800330 static string big_contents = []() {
331 string buf;
332 buf.reserve(kBigLength);
333 constexpr const char* kBigUrlContent = "abcdefghij";
334 for (size_t i = 0; i < kBigLength; i += strlen(kBigUrlContent)) {
335 buf.append(kBigUrlContent,
336 std::min(kBigLength - i, strlen(kBigUrlContent)));
337 }
338 return buf;
339 }();
340 test_utils::WriteFileString(temp_file_.path(), big_contents);
Alex Deymo2c131bb2016-05-26 16:43:13 -0700341 return "file://" + temp_file_.path();
342 }
343 string SmallUrl(in_port_t port) const override {
344 test_utils::WriteFileString(temp_file_.path(), "small contents");
345 return "file://" + temp_file_.path();
346 }
347 string ErrorUrl(in_port_t port) const override {
348 return "file:///path/to/non-existing-file";
349 }
350
351 bool IsMock() const override { return false; }
352 bool IsMulti() const override { return false; }
353 bool IsHttpSupported() const override { return false; }
Tao Bao642b32b2019-01-02 15:33:42 -0800354 bool IsFileFetcher() const override { return true; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700355
356 void IgnoreServerAborting(HttpServer* server) const override {}
357
358 HttpServer* CreateServer() override { return new NullHttpServer; }
359
360 private:
Amin Hassanied03b442020-10-26 17:21:29 -0700361 ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
Alex Deymo2c131bb2016-05-26 16:43:13 -0700362};
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800363
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700364class MultiRangeHttpFetcherOverFileFetcherFactory : public FileFetcherFactory {
Tao Bao642b32b2019-01-02 15:33:42 -0800365 public:
366 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700367 using AnyHttpFetcherFactory::NewLargeFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700368 HttpFetcher* NewLargeFetcher() override {
Tao Bao642b32b2019-01-02 15:33:42 -0800369 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(new FileFetcher());
370 ret->ClearRanges();
371 // FileFetcher doesn't support range with unspecified length.
372 ret->AddRange(0, 1);
373 // Speed up test execution.
374 ret->set_idle_seconds(1);
375 ret->set_retry_seconds(1);
376 fake_hardware_.SetIsOfficialBuild(false);
377 return ret;
378 }
379
380 // Necessary to unhide the definition in the base class.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700381 using AnyHttpFetcherFactory::NewSmallFetcher;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700382 HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }
Tao Bao642b32b2019-01-02 15:33:42 -0800383
384 bool IsMulti() const override { return true; }
385};
386
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800387//
388// Infrastructure for type tests of HTTP fetcher.
389// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
390//
391
392// Fixture class template. We use an explicit constraint to guarantee that it
393// can only be instantiated with an AnyHttpFetcherTest type, see:
394// http://www2.research.att.com/~bs/bs_faq2.html#constraints
395template <typename T>
396class HttpFetcherTest : public ::testing::Test {
397 public:
Qijiang Fanb0b6cc22020-10-15 21:54:11 +0900398#if BASE_VER < 780000 // Android
Alex Deymo535f3b72015-08-07 10:51:32 -0700399 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700400 brillo::BaseMessageLoop loop_{&base_loop_};
Qijiang Fanb0b6cc22020-10-15 21:54:11 +0900401#else // Chrome OS
402 base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
403 brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
404#endif // BASE_VER < 780000
Alex Deymo60ca1a72015-06-18 18:19:15 -0700405
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800406 T test_;
407
Alex Deymo60ca1a72015-06-18 18:19:15 -0700408 protected:
Amin Hassanib2689592019-01-13 17:04:28 -0800409 HttpFetcherTest() { loop_.SetAsCurrent(); }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700410
411 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700412 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700413 }
414
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800415 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700416 static void TypeConstraint(T* a) {
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700417 AnyHttpFetcherFactory* b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700418 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700419 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800420 }
421};
422
423// Test case types list.
Kelvin Zhangf0c73d42021-09-07 10:34:26 -0700424typedef ::testing::Types<LibcurlHttpFetcherFactory,
425 MockHttpFetcherFactory,
426 MultiRangeHttpFetcherFactory,
427 FileFetcherFactory,
428 MultiRangeHttpFetcherOverFileFetcherFactory>
Alex Deymo2c131bb2016-05-26 16:43:13 -0700429 HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000430TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
431
rspangler@google.com49fdf182009-10-10 00:57:34 +0000432class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000433 public:
Alex Deymofdd6dec2016-03-03 22:35:43 -0800434 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800435
Amin Hassani0cd9d772018-07-31 23:55:43 -0700436 bool ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymofdd6dec2016-03-03 22:35:43 -0800437 const void* bytes,
438 size_t length) override {
439 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800440 // Update counters
441 times_received_bytes_called_++;
Amin Hassani0cd9d772018-07-31 23:55:43 -0700442 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000443 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800444
Alex Deymo610277e2014-11-11 21:18:11 -0800445 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800446 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800447 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800448 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800449 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700450 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800451
452 // Update counter
453 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000454 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800455
Alex Deymo610277e2014-11-11 21:18:11 -0800456 void TransferTerminated(HttpFetcher* fetcher) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800457 times_transfer_terminated_called_++;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700458 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800459 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800460
Gilad Arnold48085ba2011-11-16 09:36:08 -0800461 // Are we expecting an error response? (default: no)
Alex Deymofdd6dec2016-03-03 22:35:43 -0800462 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800463
464 // Counters for callback invocations.
Alex Deymofdd6dec2016-03-03 22:35:43 -0800465 int times_transfer_complete_called_{0};
466 int times_transfer_terminated_called_{0};
467 int times_received_bytes_called_{0};
468
469 // The received data bytes.
470 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000471};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000472
Alex Deymo60ca1a72015-06-18 18:19:15 -0700473void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
474 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000475}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000476
477TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700478 HttpFetcherTestDelegate delegate;
479 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
480 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000481
Alex Deymo60ca1a72015-06-18 18:19:15 -0700482 unique_ptr<HttpServer> server(this->test_.CreateServer());
483 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000484
Amin Hassanib2689592019-01-13 17:04:28 -0800485 this->loop_.PostTask(FROM_HERE,
486 base::Bind(StartTransfer,
487 fetcher.get(),
488 this->test_.SmallUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700489 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800490 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000491}
492
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700493TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700494 HttpFetcherTestDelegate delegate;
495 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
496 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700497
Alex Deymo60ca1a72015-06-18 18:19:15 -0700498 unique_ptr<HttpServer> server(this->test_.CreateServer());
499 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700500
Amin Hassanib2689592019-01-13 17:04:28 -0800501 this->loop_.PostTask(
502 FROM_HERE,
503 base::Bind(
504 StartTransfer, fetcher.get(), this->test_.BigUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700505 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800506 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700507}
508
Gilad Arnold48085ba2011-11-16 09:36:08 -0800509// Issue #9648: when server returns an error HTTP response, the fetcher needs to
510// terminate transfer prematurely, rather than try to process the error payload.
511TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800512 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800513 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700514 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800515
Alex Deymo60ca1a72015-06-18 18:19:15 -0700516 // Delegate should expect an error response.
517 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800518
Alex Deymo60ca1a72015-06-18 18:19:15 -0700519 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
520 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800521
Alex Deymo60ca1a72015-06-18 18:19:15 -0700522 unique_ptr<HttpServer> server(this->test_.CreateServer());
523 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800524
Amin Hassanib2689592019-01-13 17:04:28 -0800525 this->loop_.PostTask(FROM_HERE,
526 base::Bind(StartTransfer,
527 fetcher.get(),
528 this->test_.ErrorUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700529 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800530
Alex Deymo60ca1a72015-06-18 18:19:15 -0700531 // Make sure that no bytes were received.
Alex Deymo71f67622017-02-03 21:30:24 -0800532 EXPECT_EQ(0, delegate.times_received_bytes_called_);
533 EXPECT_EQ(0U, fetcher->GetBytesDownloaded());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800534
Alex Deymo60ca1a72015-06-18 18:19:15 -0700535 // Make sure that transfer completion was signaled once, and no termination
536 // was signaled.
Alex Deymo71f67622017-02-03 21:30:24 -0800537 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
538 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800539}
540
Alex Deymofdd6dec2016-03-03 22:35:43 -0800541TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700542 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymofdd6dec2016-03-03 22:35:43 -0800543 return;
544
545 HttpFetcherTestDelegate delegate;
546 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
547 fetcher->set_delegate(&delegate);
548 fetcher->SetHeader("User-Agent", "MyTest");
549 fetcher->SetHeader("user-agent", "Override that header");
550 fetcher->SetHeader("Authorization", "Basic user:passwd");
Daniel Zheng31d9e552024-08-08 09:56:14 -0700551 fetcher->SetHeader("Cache-Control", "testControl");
552 fetcher->SetHeader("Connection", "testConnection");
Alex Deymofdd6dec2016-03-03 22:35:43 -0800553
554 // Invalid headers.
555 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
556 fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
557
558 // Hide Accept header normally added by default.
559 fetcher->SetHeader("Accept", "");
560
561 PythonHttpServer server;
562 int port = server.GetPort();
563 ASSERT_TRUE(server.started_);
564
Alex Deymo2c131bb2016-05-26 16:43:13 -0700565 this->loop_.PostTask(
566 FROM_HERE,
567 base::Bind(StartTransfer,
568 fetcher.get(),
569 LocalServerUrlForPath(port, "/echo-headers")));
Alex Deymofdd6dec2016-03-03 22:35:43 -0800570 this->loop_.Run();
571
572 EXPECT_NE(string::npos,
573 delegate.data.find("user-agent: Override that header\r\n"));
574 EXPECT_NE(string::npos,
575 delegate.data.find("Authorization: Basic user:passwd\r\n"));
Daniel Zheng31d9e552024-08-08 09:56:14 -0700576 EXPECT_NE(string::npos, delegate.data.find("Cache-Control: testControl\r\n"));
577 EXPECT_NE(string::npos, delegate.data.find("Connection: testConnection\r\n"));
Alex Deymofdd6dec2016-03-03 22:35:43 -0800578
579 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
580 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
581 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
582}
583
rspangler@google.com49fdf182009-10-10 00:57:34 +0000584class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
585 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700586 bool ReceivedBytes(HttpFetcher* fetcher,
587 const void* /* bytes */,
588 size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000589 CHECK(!paused_);
590 paused_ = true;
591 fetcher->Pause();
Amin Hassani0cd9d772018-07-31 23:55:43 -0700592 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000593 }
Alex Deymo610277e2014-11-11 21:18:11 -0800594 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700595 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000596 }
Amin Hassanib2689592019-01-13 17:04:28 -0800597 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000598 void Unpause() {
599 CHECK(paused_);
600 paused_ = false;
601 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000602 }
603 bool paused_;
604 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000605};
606
Alex Deymo60ca1a72015-06-18 18:19:15 -0700607void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
608 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000609 if (delegate->paused_)
610 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700611 // Update the task id with the new scheduled callback.
612 *my_id = MessageLoop::current()->PostDelayedTask(
613 FROM_HERE,
614 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
615 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000616}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000617
618TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800619 PausingHttpFetcherTestDelegate delegate;
620 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
621 delegate.paused_ = false;
622 delegate.fetcher_ = fetcher.get();
623 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000624
Alex Deymof2858572016-02-25 11:20:13 -0800625 unique_ptr<HttpServer> server(this->test_.CreateServer());
626 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800627
Daniel Zheng3e881aa2022-09-07 22:10:29 +0000628 MessageLoop::TaskId callback_id{};
Alex Deymof2858572016-02-25 11:20:13 -0800629 callback_id = this->loop_.PostDelayedTask(
630 FROM_HERE,
631 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
632 base::TimeDelta::FromMilliseconds(200));
633 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000634
Alex Deymof2858572016-02-25 11:20:13 -0800635 this->loop_.Run();
636 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
637}
638
639// This test will pause the fetcher while the download is not yet started
640// because it is waiting for the proxy to be resolved.
641TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700642 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymof2858572016-02-25 11:20:13 -0800643 return;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700644 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Alex Deymof2858572016-02-25 11:20:13 -0800645
646 // Saved arguments from the proxy call.
Alex Deymof2858572016-02-25 11:20:13 -0800647 fetcher->BeginTransfer("http://fake_url");
Alex Deymof2858572016-02-25 11:20:13 -0800648
649 // Pausing and unpausing while resolving the proxy should not affect anything.
650 fetcher->Pause();
651 fetcher->Unpause();
652 fetcher->Pause();
653 // Proxy resolver comes back after we paused the fetcher.
rspangler@google.com49fdf182009-10-10 00:57:34 +0000654}
655
rspangler@google.com49fdf182009-10-10 00:57:34 +0000656class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
657 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700658 bool ReceivedBytes(HttpFetcher* fetcher,
659 const void* bytes,
660 size_t length) override {
661 return true;
662 }
Alex Deymo610277e2014-11-11 21:18:11 -0800663 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800664 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700665 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000666 }
Alex Deymo610277e2014-11-11 21:18:11 -0800667 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800668 EXPECT_EQ(fetcher, fetcher_.get());
669 EXPECT_FALSE(once_);
670 EXPECT_TRUE(callback_once_);
671 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700672 // The fetcher could have a callback scheduled on the ProxyResolver that
673 // can fire after this callback. We wait until the end of the test to
674 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800675 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000676 void TerminateTransfer() {
677 CHECK(once_);
678 once_ = false;
679 fetcher_->TerminateTransfer();
680 }
Amin Hassanib2689592019-01-13 17:04:28 -0800681 void EndLoop() { MessageLoop::current()->BreakLoop(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000682 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800683 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700684 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000685};
686
Alex Deymo60ca1a72015-06-18 18:19:15 -0700687void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
688 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000689 if (delegate->once_) {
690 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700691 *my_id = MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800692 FROM_HERE, base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000693 } else {
694 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700695 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000696 }
697}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000698
699TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700700 AbortingHttpFetcherTestDelegate delegate;
701 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
702 delegate.once_ = true;
703 delegate.callback_once_ = true;
704 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000705
Alex Deymo60ca1a72015-06-18 18:19:15 -0700706 unique_ptr<HttpServer> server(this->test_.CreateServer());
707 this->test_.IgnoreServerAborting(server.get());
708 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800709
Alex Deymo60ca1a72015-06-18 18:19:15 -0700710 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000711
Alex Deymo60ca1a72015-06-18 18:19:15 -0700712 task_id = this->loop_.PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800713 FROM_HERE, base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700714 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
715
716 this->loop_.Run();
717 CHECK(!delegate.once_);
718 CHECK(!delegate.callback_once_);
719 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000720}
721
Alex Deymo71f67622017-02-03 21:30:24 -0800722TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
723 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
724 return;
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -0700725 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Alex Deymo71f67622017-02-03 21:30:24 -0800726
727 HttpFetcherTestDelegate delegate;
728 fetcher->set_delegate(&delegate);
729
Alex Deymo71f67622017-02-03 21:30:24 -0800730 fetcher->BeginTransfer("http://fake_url");
731 // Run the message loop until idle. This must call the MockProxyResolver with
732 // the request.
733 while (this->loop_.RunOnce(false)) {
734 }
Alex Deymo71f67622017-02-03 21:30:24 -0800735
736 // Terminate the transfer right before the proxy resolution response.
737 fetcher->TerminateTransfer();
738 EXPECT_EQ(0, delegate.times_received_bytes_called_);
739 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
740 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
741}
742
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000743class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
744 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700745 bool ReceivedBytes(HttpFetcher* fetcher,
746 const void* bytes,
747 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800748 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700749 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000750 }
Alex Deymo610277e2014-11-11 21:18:11 -0800751 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700752 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800753 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700754 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000755 }
Amin Hassanib2689592019-01-13 17:04:28 -0800756 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000757 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000758};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000759
760TYPED_TEST(HttpFetcherTest, FlakyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700761 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000762 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000763 {
764 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700765 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000766 fetcher->set_delegate(&delegate);
767
Ben Chan02f7c1d2014-10-18 15:18:02 -0700768 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800769 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000770
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -0700771 this->loop_.PostTask(
772 FROM_HERE,
773 base::Bind(&StartTransfer,
774 fetcher.get(),
775 LocalServerUrlForPath(
776 server->GetPort(),
777 android::base::StringPrintf("/flaky/%d/%d/%d/%d",
778 kBigLength,
779 kFlakyTruncateLength,
780 kFlakySleepEvery,
781 kFlakySleepSecs))));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700782 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000783
784 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800785 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800786 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000787 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
788 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
789 }
790 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000791}
792
Chris Sosa0a364bb2014-06-10 18:18:24 -0700793// This delegate kills the server attached to it after receiving any bytes.
794// This can be used for testing what happens when you try to fetch data and
795// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700796class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
797 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700798 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700799 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700800
Alex Deymo610277e2014-11-11 21:18:11 -0800801 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700802 if (server_) {
803 LOG(INFO) << "Stopping server in destructor";
Alex Deymob20de692017-02-05 07:47:37 +0000804 server_.reset();
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700805 LOG(INFO) << "server stopped";
806 }
807 }
808
Amin Hassani0cd9d772018-07-31 23:55:43 -0700809 bool ReceivedBytes(HttpFetcher* fetcher,
810 const void* bytes,
811 size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700812 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700813 LOG(INFO) << "Stopping server in ReceivedBytes";
Alex Deymob20de692017-02-05 07:47:37 +0000814 server_.reset();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700815 LOG(INFO) << "server stopped";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700816 }
Amin Hassani0cd9d772018-07-31 23:55:43 -0700817 return true;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700818 }
Alex Deymo610277e2014-11-11 21:18:11 -0800819 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700820 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700821 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymob20de692017-02-05 07:47:37 +0000822 times_transfer_complete_called_++;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700823 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700824 }
Alex Deymo610277e2014-11-11 21:18:11 -0800825 void TransferTerminated(HttpFetcher* fetcher) override {
Alex Deymob20de692017-02-05 07:47:37 +0000826 times_transfer_terminated_called_++;
827 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800828 }
Alex Deymob20de692017-02-05 07:47:37 +0000829 unique_ptr<PythonHttpServer> server_;
830 int times_transfer_terminated_called_{0};
831 int times_transfer_complete_called_{0};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700832};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700833
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700834TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700835 // This test ensures that a fetcher responds correctly when a server isn't
836 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800837 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700838 return;
Alex Deymob20de692017-02-05 07:47:37 +0000839 FailureHttpFetcherTestDelegate delegate(nullptr);
840 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
841 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700842
Alex Deymob20de692017-02-05 07:47:37 +0000843 this->loop_.PostTask(
844 FROM_HERE,
845 base::Bind(
846 StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
847 this->loop_.Run();
848 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
849 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700850
Alex Deymob20de692017-02-05 07:47:37 +0000851 // Exiting and testing happens in the delegate
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700852}
853
Alex Deymof123ae22015-09-24 14:59:43 -0700854TYPED_TEST(HttpFetcherTest, NoResponseTest) {
855 // This test starts a new http server but the server doesn't respond and just
856 // closes the connection.
857 if (this->test_.IsMock())
858 return;
859
860 PythonHttpServer* server = new PythonHttpServer();
861 int port = server->GetPort();
862 ASSERT_TRUE(server->started_);
863
864 // Handles destruction and claims ownership.
865 FailureHttpFetcherTestDelegate delegate(server);
866 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
867 fetcher->set_delegate(&delegate);
868 // The server will not reply at all, so we can limit the execution time of the
869 // test by reducing the low-speed timeout to something small. The test will
870 // finish once the TimeoutCallback() triggers (every second) and the timeout
871 // expired.
872 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
873
Amin Hassanib2689592019-01-13 17:04:28 -0800874 this->loop_.PostTask(
875 FROM_HERE,
876 base::Bind(
877 StartTransfer, fetcher.get(), LocalServerUrlForPath(port, "/hang")));
Alex Deymof123ae22015-09-24 14:59:43 -0700878 this->loop_.Run();
Alex Deymob20de692017-02-05 07:47:37 +0000879 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
880 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Alex Deymof123ae22015-09-24 14:59:43 -0700881
882 // Check that no other callback runs in the next two seconds. That would
883 // indicate a leaked callback.
884 bool timeout = false;
Luis Hector Chavezf1cf3482016-07-19 14:29:19 -0700885 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
886 base::Unretained(&timeout));
Amin Hassanib2689592019-01-13 17:04:28 -0800887 this->loop_.PostDelayedTask(
888 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
Alex Deymof123ae22015-09-24 14:59:43 -0700889 EXPECT_TRUE(this->loop_.RunOnce(true));
890 EXPECT_TRUE(timeout);
891}
892
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700893TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700894 // This test starts a new http server and kills it after receiving its first
895 // set of bytes. It test whether or not our fetcher eventually gives up on
896 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800897 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700898 return;
Alex Deymob20de692017-02-05 07:47:37 +0000899 PythonHttpServer* server = new PythonHttpServer();
900 int port = server->GetPort();
901 ASSERT_TRUE(server->started_);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700902
Alex Deymob20de692017-02-05 07:47:37 +0000903 // Handles destruction and claims ownership.
904 FailureHttpFetcherTestDelegate delegate(server);
905 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
906 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700907
Alex Deymob20de692017-02-05 07:47:37 +0000908 this->loop_.PostTask(
909 FROM_HERE,
910 base::Bind(StartTransfer,
911 fetcher.get(),
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -0700912 LocalServerUrlForPath(
913 port,
914 android::base::StringPrintf("/flaky/%d/%d/%d/%d",
915 kBigLength,
916 kFlakyTruncateLength,
917 kFlakySleepEvery,
918 kFlakySleepSecs))));
Alex Deymob20de692017-02-05 07:47:37 +0000919 this->loop_.Run();
920 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
921 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700922
Alex Deymob20de692017-02-05 07:47:37 +0000923 // Exiting and testing happens in the delegate
924}
925
926// Test that we can cancel a transfer while it is still trying to connect to the
927// server. This test kills the server after a few bytes are received.
928TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
929 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
930 return;
931
932 PythonHttpServer* server = new PythonHttpServer();
933 int port = server->GetPort();
934 ASSERT_TRUE(server->started_);
935
936 // Handles destruction and claims ownership.
937 FailureHttpFetcherTestDelegate delegate(server);
938 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
939 fetcher->set_delegate(&delegate);
940
941 this->loop_.PostTask(
942 FROM_HERE,
943 base::Bind(StartTransfer,
944 fetcher.get(),
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -0700945 LocalServerUrlForPath(
946 port,
947 android::base::StringPrintf("/flaky/%d/%d/%d/%d",
948 kBigLength,
949 kFlakyTruncateLength,
950 kFlakySleepEvery,
951 kFlakySleepSecs))));
Alex Deymob20de692017-02-05 07:47:37 +0000952 // Terminating the transfer after 3 seconds gives it a chance to contact the
953 // server and enter the retry loop.
954 this->loop_.PostDelayedTask(FROM_HERE,
955 base::Bind(&HttpFetcher::TerminateTransfer,
956 base::Unretained(fetcher.get())),
957 base::TimeDelta::FromSeconds(3));
958
959 // Exiting and testing happens in the delegate.
960 this->loop_.Run();
961 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
962 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
963
964 // Check that no other callback runs in the next two seconds. That would
965 // indicate a leaked callback.
966 bool timeout = false;
967 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
968 base::Unretained(&timeout));
969 this->loop_.PostDelayedTask(
970 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
971 EXPECT_TRUE(this->loop_.RunOnce(true));
972 EXPECT_TRUE(timeout);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700973}
974
Amin Hassanib2689592019-01-13 17:04:28 -0800975const HttpResponseCode kRedirectCodes[] = {kHttpResponseMovedPermanently,
976 kHttpResponseFound,
977 kHttpResponseSeeOther,
978 kHttpResponseTempRedirect};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700979
980class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
981 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700982 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700983 : expected_successful_(expected_successful) {}
Amin Hassani0cd9d772018-07-31 23:55:43 -0700984 bool ReceivedBytes(HttpFetcher* fetcher,
985 const void* bytes,
986 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800987 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700988 return true;
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700989 }
Alex Deymo610277e2014-11-11 21:18:11 -0800990 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700991 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700992 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800993 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700994 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800995 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
996 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700997 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700998 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700999 }
Amin Hassanib2689592019-01-13 17:04:28 -08001000 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001001 bool expected_successful_;
1002 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001003};
1004
1005// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001006void RedirectTest(const HttpServer* server,
1007 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001008 const string& url,
1009 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001010 RedirectHttpFetcherTestDelegate delegate(expected_successful);
1011 unique_ptr<HttpFetcher> fetcher(http_fetcher);
1012 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001013
Amin Hassanib2689592019-01-13 17:04:28 -08001014 MessageLoop::current()->PostTask(
1015 FROM_HERE,
1016 base::Bind(StartTransfer,
1017 fetcher.get(),
1018 LocalServerUrlForPath(server->GetPort(), url)));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001019 MessageLoop::current()->Run();
1020 if (expected_successful) {
1021 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -08001022 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -07001023 for (int i = 0; i < kMediumLength; i += 10) {
1024 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
1025 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001026 }
1027 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001028}
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001029
1030TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001031 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001032 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001033
Ben Chan02f7c1d2014-10-18 15:18:02 -07001034 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001035 ASSERT_TRUE(server->started_);
1036
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -07001037 for (size_t c = 0; c < base::size(kRedirectCodes); ++c) {
1038 const string url = android::base::StringPrintf(
Amin Hassanib2689592019-01-13 17:04:28 -08001039 "/redirect/%d/download/%d", kRedirectCodes[c], kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001040 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001041 }
1042}
1043
1044TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001045 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001046 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001047
Ben Chan02f7c1d2014-10-18 15:18:02 -07001048 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001049 ASSERT_TRUE(server->started_);
1050
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001051 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001052 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -07001053 url += android::base::StringPrintf(
1054 "/redirect/%d", kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001055 }
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -07001056 url += android::base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001057 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001058}
1059
1060TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
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
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001067 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001068 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -07001069 url += android::base::StringPrintf(
1070 "/redirect/%d", kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001071 }
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -07001072 url += android::base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001073 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001074}
1075
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001076class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1077 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001078 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001079 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001080
Amin Hassani0cd9d772018-07-31 23:55:43 -07001081 bool ReceivedBytes(HttpFetcher* fetcher,
1082 const void* bytes,
1083 size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001084 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001085 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001086 return true;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001087 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001088
Alex Deymo610277e2014-11-11 21:18:11 -08001089 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001090 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001091 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001092 if (expected_response_code_ != 0)
1093 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001094 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -07001095 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001096 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001097 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001098
Amin Hassanib2689592019-01-13 17:04:28 -08001099 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001100
Ben Chan02f7c1d2014-10-18 15:18:02 -07001101 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001102 int expected_response_code_;
1103 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001104};
1105
1106void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -03001107 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001108 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -07001109 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001110 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -08001111 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001112 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001113 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1114 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001115
Alex Deymo60ca1a72015-06-18 18:19:15 -07001116 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -08001117 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001118 ASSERT_TRUE(multi_fetcher);
1119 multi_fetcher->ClearRanges();
1120 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
Amin Hassanib2689592019-01-13 17:04:28 -08001121 e = ranges.end();
1122 it != e;
1123 ++it) {
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -07001124 string tmp_str = android::base::StringPrintf("%jd+", it->first);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001125 if (it->second > 0) {
Kokoa Matsuda11c3da62024-10-23 13:40:44 +09001126 android::base::StringAppendF(&tmp_str, "%jd", it->second);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001127 multi_fetcher->AddRange(it->first, it->second);
1128 } else {
Kokoa Matsuda11c3da62024-10-23 13:40:44 +09001129 android::base::StringAppendF(&tmp_str, "?");
Alex Deymo60ca1a72015-06-18 18:19:15 -07001130 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001131 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001132 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001133 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001134 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001135 multi_fetcher->set_delegate(&delegate);
1136
1137 MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -08001138 FROM_HERE, base::Bind(StartTransfer, multi_fetcher, url));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001139 MessageLoop::current()->Run();
1140
1141 EXPECT_EQ(expected_size, delegate.data.size());
1142 EXPECT_EQ(expected_prefix,
1143 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001144}
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001145
Darin Petkov9ce452b2010-11-17 14:33:28 -08001146TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001147 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001148 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001149
Ben Chan02f7c1d2014-10-18 15:18:02 -07001150 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001151 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001152
Ben Chanf9cb98c2014-09-21 18:31:30 -07001153 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001154 ranges.push_back(make_pair(0, 25));
Tao Bao642b32b2019-01-02 15:33:42 -08001155 ranges.push_back(make_pair(99, 17));
1156 MultiTest(this->test_.NewLargeFetcher(),
1157 this->test_.fake_hardware(),
1158 this->test_.BigUrl(server->GetPort()),
1159 ranges,
1160 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1161 25 + 17,
1162 this->test_.IsFileFetcher() ? kHttpResponseOk
1163 : kHttpResponsePartialContent);
1164}
1165
1166TYPED_TEST(HttpFetcherTest, MultiHttpFetcherUnspecifiedEndTest) {
1167 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1168 return;
1169
1170 unique_ptr<HttpServer> server(this->test_.CreateServer());
1171 ASSERT_TRUE(server->started_);
1172
1173 vector<pair<off_t, off_t>> ranges;
1174 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001175 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001176 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001177 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001178 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001179 ranges,
1180 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001181 kBigLength - (99 - 25),
1182 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001183}
1184
1185TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001186 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001187 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001188
Ben Chan02f7c1d2014-10-18 15:18:02 -07001189 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001190 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001191
Ben Chanf9cb98c2014-09-21 18:31:30 -07001192 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001193 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001194 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001195 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001196 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001197 ranges,
1198 "abcdefghijabcdefghijabcd",
1199 24,
Tao Bao642b32b2019-01-02 15:33:42 -08001200 this->test_.IsFileFetcher() ? kHttpResponseOk
1201 : kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001202}
1203
1204TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001205 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001206 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001207
Ben Chan02f7c1d2014-10-18 15:18:02 -07001208 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001209 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001210
Ben Chanf9cb98c2014-09-21 18:31:30 -07001211 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001212 ranges.push_back(make_pair(kBigLength - 2, 0));
1213 ranges.push_back(make_pair(kBigLength - 3, 0));
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 "ijhij",
1219 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001220 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001221}
1222
1223TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001224 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001225 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001226
Ben Chan02f7c1d2014-10-18 15:18:02 -07001227 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001228 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001229
Ben Chanf9cb98c2014-09-21 18:31:30 -07001230 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001231 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001232 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001233 LOG(INFO) << "i = " << i;
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 "ij",
1239 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001240 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001241 ranges.push_back(make_pair(0, 5));
1242 }
1243}
1244
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001245// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1246// should retry with other proxies listed before giving up.
1247//
1248// (1) successful recovery: The offset fetch will fail twice but succeed with
1249// the third proxy.
1250TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001251 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001252 return;
1253
Ben Chan02f7c1d2014-10-18 15:18:02 -07001254 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001255 ASSERT_TRUE(server->started_);
1256
Ben Chanf9cb98c2014-09-21 18:31:30 -07001257 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001258 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001259 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001260 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001261 this->test_.fake_hardware(),
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -07001262 LocalServerUrlForPath(server->GetPort(),
1263 android::base::StringPrintf(
1264 "/error-if-offset/%d/2", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001265 ranges,
1266 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1267 kBigLength - (99 - 25),
1268 kHttpResponsePartialContent);
1269}
1270
1271// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1272// fetcher will signal a (failed) completed transfer to the delegate.
1273TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001274 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001275 return;
1276
Ben Chan02f7c1d2014-10-18 15:18:02 -07001277 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001278 ASSERT_TRUE(server->started_);
1279
Ben Chanf9cb98c2014-09-21 18:31:30 -07001280 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001281 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001282 ranges.push_back(make_pair(99, 0));
Kelvin Zhangc7a1d1f2022-07-29 13:36:29 -07001283 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001284 this->test_.fake_hardware(),
Kelvin Zhangb9a9aa22024-10-15 10:38:35 -07001285 LocalServerUrlForPath(server->GetPort(),
1286 android::base::StringPrintf(
1287 "/error-if-offset/%d/3", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001288 ranges,
1289 "abcdefghijabcdefghijabcde", // only received the first chunk
1290 25,
1291 kHttpResponseUndefined);
1292}
1293
Alex Deymo4ea2d922017-02-05 07:35:32 +00001294// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1295class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1296 public:
1297 explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1298 : terminate_trigger_bytes_(terminate_trigger_bytes) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001299
Amin Hassani0cd9d772018-07-31 23:55:43 -07001300 bool ReceivedBytes(HttpFetcher* fetcher,
Alex Deymo4ea2d922017-02-05 07:35:32 +00001301 const void* bytes,
1302 size_t length) override {
1303 LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
1304 EXPECT_EQ(fetcher, fetcher_.get());
Tao Bao642b32b2019-01-02 15:33:42 -08001305 bool should_terminate = false;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001306 if (bytes_downloaded_ < terminate_trigger_bytes_ &&
1307 bytes_downloaded_ + length >= terminate_trigger_bytes_) {
1308 MessageLoop::current()->PostTask(
1309 FROM_HERE,
1310 base::Bind(&HttpFetcher::TerminateTransfer,
1311 base::Unretained(fetcher_.get())));
Tao Bao642b32b2019-01-02 15:33:42 -08001312 should_terminate = true;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001313 }
1314 bytes_downloaded_ += length;
Tao Bao642b32b2019-01-02 15:33:42 -08001315 return !should_terminate;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001316 }
1317
1318 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1319 ADD_FAILURE() << "TransferComplete called but expected a failure";
1320 // Destroy the fetcher (because we're allowed to).
1321 fetcher_.reset(nullptr);
1322 MessageLoop::current()->BreakLoop();
1323 }
1324
1325 void TransferTerminated(HttpFetcher* fetcher) override {
1326 // Destroy the fetcher (because we're allowed to).
1327 fetcher_.reset(nullptr);
1328 MessageLoop::current()->BreakLoop();
1329 }
1330
1331 unique_ptr<HttpFetcher> fetcher_;
1332 size_t bytes_downloaded_{0};
1333 size_t terminate_trigger_bytes_;
1334};
Alex Deymo4ea2d922017-02-05 07:35:32 +00001335
1336TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
1337 if (!this->test_.IsMulti())
1338 return;
1339 const size_t kRangeTrigger = 1000;
1340 MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
1341
1342 unique_ptr<HttpServer> server(this->test_.CreateServer());
1343 ASSERT_TRUE(server->started_);
1344
1345 MultiRangeHttpFetcher* multi_fetcher =
1346 static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
1347 ASSERT_TRUE(multi_fetcher);
1348 // Transfer ownership of the fetcher to the delegate.
1349 delegate.fetcher_.reset(multi_fetcher);
1350 multi_fetcher->set_delegate(&delegate);
1351
1352 multi_fetcher->ClearRanges();
1353 multi_fetcher->AddRange(45, kRangeTrigger);
1354 multi_fetcher->AddRange(2000, 100);
1355
1356 this->test_.fake_hardware()->SetIsOfficialBuild(false);
1357
1358 StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
1359 MessageLoop::current()->Run();
1360
1361 // Check that the delegate made it to the trigger point.
1362 EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
1363}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001364
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001365class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001366 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -07001367 bool ReceivedBytes(HttpFetcher* fetcher,
1368 const void* bytes,
1369 size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001370 ADD_FAILURE();
Amin Hassani0cd9d772018-07-31 23:55:43 -07001371 return true;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001372 }
Alex Deymo610277e2014-11-11 21:18:11 -08001373 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001374 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001375 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001376 }
Amin Hassanib2689592019-01-13 17:04:28 -08001377 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001378};
1379
Kelvin Zhangf0c73d42021-09-07 10:34:26 -07001380void BlockedTransferTestHelper(AnyHttpFetcherFactory* fetcher_test,
Alex Deymo60ca1a72015-06-18 18:19:15 -07001381 bool is_official_build) {
1382 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1383 return;
1384
1385 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1386 ASSERT_TRUE(server->started_);
1387
1388 BlockedTransferTestDelegate delegate;
1389 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1390 LOG(INFO) << "is_official_build: " << is_official_build;
1391 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001392 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001393 fetcher->set_delegate(&delegate);
1394
Amin Hassanib2689592019-01-13 17:04:28 -08001395 MessageLoop::current()->PostTask(
1396 FROM_HERE,
1397 base::Bind(
1398 StartTransfer,
1399 fetcher.get(),
1400 LocalServerUrlForPath(server->GetPort(),
1401 fetcher_test->SmallUrl(server->GetPort()))));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001402 MessageLoop::current()->Run();
1403}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001404
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001405TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001406 BlockedTransferTestHelper(&this->test_, false);
1407}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001408
Alex Deymo60ca1a72015-06-18 18:19:15 -07001409TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1410 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001411}
1412
Kelvin Zhangf0c73d42021-09-07 10:34:26 -07001413} // namespace
1414
rspangler@google.com49fdf182009-10-10 00:57:34 +00001415} // namespace chromeos_update_engine