blob: 9338087dbcda2cc62bcb89dc3618bfc7faed8bd4 [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>
Alex Deymo535f3b72015-08-07 10:51:32 -070031#include <base/message_loop/message_loop.h>
hscham00b6aa22020-02-20 12:32:06 +090032#include <base/stl_util.h>
Alex Deymo535f3b72015-08-07 10:51:32 -070033#include <base/strings/string_number_conversions.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070034#include <base/strings/string_util.h>
35#include <base/strings/stringprintf.h>
36#include <base/time/time.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070037#include <brillo/message_loops/base_message_loop.h>
38#include <brillo/message_loops/message_loop.h>
39#include <brillo/message_loops/message_loop_utils.h>
Amin Hassani4bd46b32020-09-15 15:30:09 -070040#ifdef __CHROMEOS__
41#include <brillo/process/process.h>
42#else
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070043#include <brillo/process.h>
Amin Hassani4bd46b32020-09-15 15:30:09 -070044#endif // __CHROMEOS__
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070045#include <brillo/streams/file_stream.h>
46#include <brillo/streams/stream.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080047#include <gtest/gtest.h>
48
Alex Deymoc1c17b42015-11-23 03:53:15 -030049#include "update_engine/common/fake_hardware.h"
Alex Deymo2c131bb2016-05-26 16:43:13 -070050#include "update_engine/common/file_fetcher.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080051#include "update_engine/common/http_common.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080052#include "update_engine/common/mock_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070053#include "update_engine/common/mock_proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080054#include "update_engine/common/multi_range_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070055#include "update_engine/common/proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080056#include "update_engine/common/test_utils.h"
57#include "update_engine/common/utils.h"
Alex Deymo14c0da82016-07-20 16:45:45 -070058#include "update_engine/libcurl_http_fetcher.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000059
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070060using brillo::MessageLoop;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070061using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080062using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000063using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070064using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000065using std::vector;
Amin Hassanib2689592019-01-13 17:04:28 -080066using testing::_;
Alex Deymof2858572016-02-25 11:20:13 -080067using testing::DoAll;
68using testing::Return;
69using testing::SaveArg;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000070
Gilad Arnold9bedeb52011-11-17 16:19:57 -080071namespace {
72
Amin Hassanib2689592019-01-13 17:04:28 -080073const int kBigLength = 100000;
74const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080075const int kFlakyTruncateLength = 29000;
Amin Hassanib2689592019-01-13 17:04:28 -080076const int kFlakySleepEvery = 3;
77const int kFlakySleepSecs = 10;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080078
79} // namespace
80
rspangler@google.com49fdf182009-10-10 00:57:34 +000081namespace chromeos_update_engine {
82
Amin Hassanib2689592019-01-13 17:04:28 -080083static const char* kUnusedUrl = "unused://unused";
Gilad Arnold9bedeb52011-11-17 16:19:57 -080084
Amin Hassanib2689592019-01-13 17:04:28 -080085static inline string LocalServerUrlForPath(in_port_t port, const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070086 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Amin Hassanib2689592019-01-13 17:04:28 -080087 return base::StringPrintf(
88 "http://127.0.0.1%s%s", port_str.c_str(), path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000089}
90
Gilad Arnold9bedeb52011-11-17 16:19:57 -080091//
92// Class hierarchy for HTTP server implementations.
93//
94
95class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000096 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080097 // This makes it an abstract class (dirty but works).
98 virtual ~HttpServer() = 0;
99
Amin Hassanib2689592019-01-13 17:04:28 -0800100 virtual in_port_t GetPort() const { return 0; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700101
rspangler@google.com49fdf182009-10-10 00:57:34 +0000102 bool started_;
103};
104
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800105HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000106
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800107class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000108 public:
Amin Hassanib2689592019-01-13 17:04:28 -0800109 NullHttpServer() { started_ = true; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000110};
111
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800112class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000113 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700114 PythonHttpServer() : port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000115 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700116
117 // Spawn the server process.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700118 unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
Sen Jiang260f03b2016-03-21 15:34:58 -0700119 http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
Alex Deymo535f3b72015-08-07 10:51:32 -0700120 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
121
122 if (!http_server->Start()) {
123 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000124 return;
125 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700126 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700127
128 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700129 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700130 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
131 if (!stdout)
132 return;
133
134 vector<char> buf(128);
135 string line;
136 while (line.find('\n') == string::npos) {
137 size_t read;
138 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
139 ADD_FAILURE() << "error reading http server stdout";
140 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700141 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700142 line.append(buf.data(), read);
143 if (read == 0)
144 break;
145 }
146 // Parse the port from the output line.
147 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
148 if (line.size() < listening_msg_prefix_len) {
149 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700150 return;
151 }
152
Alex Deymo535f3b72015-08-07 10:51:32 -0700153 EXPECT_EQ(kServerListeningMsgPrefix,
154 line.substr(0, listening_msg_prefix_len));
155 string port_str = line.substr(listening_msg_prefix_len);
156 port_str.resize(port_str.find('\n'));
157 EXPECT_TRUE(base::StringToUint(port_str, &port_));
158
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700159 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700160 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700161
162 // Any failure before this point will SIGKILL the test server if started
163 // when the |http_server| goes out of scope.
164 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000165 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800166
rspangler@google.com49fdf182009-10-10 00:57:34 +0000167 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700168 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700169 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000170 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700171 // Wait up to 10 seconds for the process to finish. Destroying the process
172 // will kill it with a SIGKILL otherwise.
173 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000174 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800175
Amin Hassanib2689592019-01-13 17:04:28 -0800176 in_port_t GetPort() const override { return port_; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700177
178 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700179 static const char* kServerListeningMsgPrefix;
180
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700181 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700182 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000183};
184
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700185const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
186
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800187//
188// Class hierarchy for HTTP fetcher test wrappers.
189//
190
191class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000192 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700193 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700194 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700195
Alex Deymof2858572016-02-25 11:20:13 -0800196 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
197 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
198 proxy_resolver_.set_num_proxies(num_proxies);
199 return NewLargeFetcher(&proxy_resolver_);
200 }
Amin Hassanib2689592019-01-13 17:04:28 -0800201 HttpFetcher* NewLargeFetcher() { return NewLargeFetcher(1); }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800202
Alex Deymof2858572016-02-25 11:20:13 -0800203 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800204 HttpFetcher* NewSmallFetcher() {
Alex Deymof2858572016-02-25 11:20:13 -0800205 proxy_resolver_.set_num_proxies(1);
206 return NewSmallFetcher(&proxy_resolver_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800207 }
208
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700209 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
210 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
211 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800212
213 virtual bool IsMock() const = 0;
214 virtual bool IsMulti() const = 0;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700215 virtual bool IsHttpSupported() const = 0;
Tao Bao642b32b2019-01-02 15:33:42 -0800216 virtual bool IsFileFetcher() const = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800217
218 virtual void IgnoreServerAborting(HttpServer* server) const {}
219
Alex Deymo60ca1a72015-06-18 18:19:15 -0700220 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800221
Amin Hassanib2689592019-01-13 17:04:28 -0800222 FakeHardware* fake_hardware() { return &fake_hardware_; }
Alex Deymoc1c17b42015-11-23 03:53:15 -0300223
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800224 protected:
225 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300226 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800227};
228
229class MockHttpFetcherTest : public AnyHttpFetcherTest {
230 public:
231 // Necessary to unhide the definition in the base class.
232 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800233 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700234 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800235 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800236 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800237 }
238
239 // Necessary to unhide the definition in the base class.
240 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800241 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
242 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800243 }
244
Alex Deymo610277e2014-11-11 21:18:11 -0800245 bool IsMock() const override { return true; }
246 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700247 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800248 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800249
Amin Hassanib2689592019-01-13 17:04:28 -0800250 HttpServer* CreateServer() override { return new NullHttpServer; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800251};
252
253class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
254 public:
255 // Necessary to unhide the definition in the base class.
256 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800257 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
258 LibcurlHttpFetcher* ret =
259 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700260 // Speed up test execution.
261 ret->set_idle_seconds(1);
262 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300263 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000264 return ret;
265 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800266
267 // Necessary to unhide the definition in the base class.
268 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800269 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
270 return NewLargeFetcher(proxy_resolver);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000271 }
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(
275 port, 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
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800296class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
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.
299 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800300 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
301 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
302 new LibcurlHttpFetcher(proxy_resolver, &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.
313 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800314 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
315 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800316 }
317
Alex Deymo610277e2014-11-11 21:18:11 -0800318 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700319};
320
Alex Deymo2c131bb2016-05-26 16:43:13 -0700321class FileFetcherTest : public AnyHttpFetcherTest {
322 public:
323 // Necessary to unhide the definition in the base class.
324 using AnyHttpFetcherTest::NewLargeFetcher;
325 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
326 return new FileFetcher();
327 }
328
329 // Necessary to unhide the definition in the base class.
330 using AnyHttpFetcherTest::NewSmallFetcher;
331 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
332 return NewLargeFetcher(proxy_resolver);
333 }
334
335 string BigUrl(in_port_t port) const override {
Tao Bao642b32b2019-01-02 15:33:42 -0800336 static string big_contents = []() {
337 string buf;
338 buf.reserve(kBigLength);
339 constexpr const char* kBigUrlContent = "abcdefghij";
340 for (size_t i = 0; i < kBigLength; i += strlen(kBigUrlContent)) {
341 buf.append(kBigUrlContent,
342 std::min(kBigLength - i, strlen(kBigUrlContent)));
343 }
344 return buf;
345 }();
346 test_utils::WriteFileString(temp_file_.path(), big_contents);
Alex Deymo2c131bb2016-05-26 16:43:13 -0700347 return "file://" + temp_file_.path();
348 }
349 string SmallUrl(in_port_t port) const override {
350 test_utils::WriteFileString(temp_file_.path(), "small contents");
351 return "file://" + temp_file_.path();
352 }
353 string ErrorUrl(in_port_t port) const override {
354 return "file:///path/to/non-existing-file";
355 }
356
357 bool IsMock() const override { return false; }
358 bool IsMulti() const override { return false; }
359 bool IsHttpSupported() const override { return false; }
Tao Bao642b32b2019-01-02 15:33:42 -0800360 bool IsFileFetcher() const override { return true; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700361
362 void IgnoreServerAborting(HttpServer* server) const override {}
363
364 HttpServer* CreateServer() override { return new NullHttpServer; }
365
366 private:
367 test_utils::ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
368};
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800369
Tao Bao642b32b2019-01-02 15:33:42 -0800370class MultiRangeHttpFetcherOverFileFetcherTest : public FileFetcherTest {
371 public:
372 // Necessary to unhide the definition in the base class.
373 using AnyHttpFetcherTest::NewLargeFetcher;
374 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
375 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(new FileFetcher());
376 ret->ClearRanges();
377 // FileFetcher doesn't support range with unspecified length.
378 ret->AddRange(0, 1);
379 // Speed up test execution.
380 ret->set_idle_seconds(1);
381 ret->set_retry_seconds(1);
382 fake_hardware_.SetIsOfficialBuild(false);
383 return ret;
384 }
385
386 // Necessary to unhide the definition in the base class.
387 using AnyHttpFetcherTest::NewSmallFetcher;
388 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
389 return NewLargeFetcher(proxy_resolver);
390 }
391
392 bool IsMulti() const override { return true; }
393};
394
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800395//
396// Infrastructure for type tests of HTTP fetcher.
397// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
398//
399
400// Fixture class template. We use an explicit constraint to guarantee that it
401// can only be instantiated with an AnyHttpFetcherTest type, see:
402// http://www2.research.att.com/~bs/bs_faq2.html#constraints
403template <typename T>
404class HttpFetcherTest : public ::testing::Test {
405 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700406 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700407 brillo::BaseMessageLoop loop_{&base_loop_};
Alex Deymo60ca1a72015-06-18 18:19:15 -0700408
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800409 T test_;
410
Alex Deymo60ca1a72015-06-18 18:19:15 -0700411 protected:
Amin Hassanib2689592019-01-13 17:04:28 -0800412 HttpFetcherTest() { loop_.SetAsCurrent(); }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700413
414 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700415 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700416 }
417
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800418 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700419 static void TypeConstraint(T* a) {
Amin Hassanib2689592019-01-13 17:04:28 -0800420 AnyHttpFetcherTest* b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700421 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700422 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800423 }
424};
425
426// Test case types list.
427typedef ::testing::Types<LibcurlHttpFetcherTest,
428 MockHttpFetcherTest,
Alex Deymo2c131bb2016-05-26 16:43:13 -0700429 MultiRangeHttpFetcherTest,
Tao Bao642b32b2019-01-02 15:33:42 -0800430 FileFetcherTest,
431 MultiRangeHttpFetcherOverFileFetcherTest>
Alex Deymo2c131bb2016-05-26 16:43:13 -0700432 HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000433TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
434
435namespace {
436class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000437 public:
Alex Deymofdd6dec2016-03-03 22:35:43 -0800438 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800439
Amin Hassani0cd9d772018-07-31 23:55:43 -0700440 bool ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymofdd6dec2016-03-03 22:35:43 -0800441 const void* bytes,
442 size_t length) override {
443 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800444 // Update counters
445 times_received_bytes_called_++;
Amin Hassani0cd9d772018-07-31 23:55:43 -0700446 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000447 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800448
Alex Deymo610277e2014-11-11 21:18:11 -0800449 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800450 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800451 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800452 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800453 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700454 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800455
456 // Update counter
457 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000458 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800459
Alex Deymo610277e2014-11-11 21:18:11 -0800460 void TransferTerminated(HttpFetcher* fetcher) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800461 times_transfer_terminated_called_++;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700462 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800463 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800464
Gilad Arnold48085ba2011-11-16 09:36:08 -0800465 // Are we expecting an error response? (default: no)
Alex Deymofdd6dec2016-03-03 22:35:43 -0800466 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800467
468 // Counters for callback invocations.
Alex Deymofdd6dec2016-03-03 22:35:43 -0800469 int times_transfer_complete_called_{0};
470 int times_transfer_terminated_called_{0};
471 int times_received_bytes_called_{0};
472
473 // The received data bytes.
474 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000475};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000476
Alex Deymo60ca1a72015-06-18 18:19:15 -0700477void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
478 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000479}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700480} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000481
482TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700483 HttpFetcherTestDelegate delegate;
484 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
485 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000486
Alex Deymo60ca1a72015-06-18 18:19:15 -0700487 unique_ptr<HttpServer> server(this->test_.CreateServer());
488 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000489
Amin Hassanib2689592019-01-13 17:04:28 -0800490 this->loop_.PostTask(FROM_HERE,
491 base::Bind(StartTransfer,
492 fetcher.get(),
493 this->test_.SmallUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700494 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800495 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000496}
497
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700498TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700499 HttpFetcherTestDelegate delegate;
500 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
501 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700502
Alex Deymo60ca1a72015-06-18 18:19:15 -0700503 unique_ptr<HttpServer> server(this->test_.CreateServer());
504 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700505
Amin Hassanib2689592019-01-13 17:04:28 -0800506 this->loop_.PostTask(
507 FROM_HERE,
508 base::Bind(
509 StartTransfer, fetcher.get(), this->test_.BigUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700510 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800511 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700512}
513
Gilad Arnold48085ba2011-11-16 09:36:08 -0800514// Issue #9648: when server returns an error HTTP response, the fetcher needs to
515// terminate transfer prematurely, rather than try to process the error payload.
516TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800517 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800518 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700519 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800520
Alex Deymo60ca1a72015-06-18 18:19:15 -0700521 // Delegate should expect an error response.
522 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800523
Alex Deymo60ca1a72015-06-18 18:19:15 -0700524 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
525 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800526
Alex Deymo60ca1a72015-06-18 18:19:15 -0700527 unique_ptr<HttpServer> server(this->test_.CreateServer());
528 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800529
Amin Hassanib2689592019-01-13 17:04:28 -0800530 this->loop_.PostTask(FROM_HERE,
531 base::Bind(StartTransfer,
532 fetcher.get(),
533 this->test_.ErrorUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700534 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800535
Alex Deymo60ca1a72015-06-18 18:19:15 -0700536 // Make sure that no bytes were received.
Alex Deymo71f67622017-02-03 21:30:24 -0800537 EXPECT_EQ(0, delegate.times_received_bytes_called_);
538 EXPECT_EQ(0U, fetcher->GetBytesDownloaded());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800539
Alex Deymo60ca1a72015-06-18 18:19:15 -0700540 // Make sure that transfer completion was signaled once, and no termination
541 // was signaled.
Alex Deymo71f67622017-02-03 21:30:24 -0800542 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
543 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800544}
545
Alex Deymofdd6dec2016-03-03 22:35:43 -0800546TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700547 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymofdd6dec2016-03-03 22:35:43 -0800548 return;
549
550 HttpFetcherTestDelegate delegate;
551 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
552 fetcher->set_delegate(&delegate);
553 fetcher->SetHeader("User-Agent", "MyTest");
554 fetcher->SetHeader("user-agent", "Override that header");
555 fetcher->SetHeader("Authorization", "Basic user:passwd");
556
557 // Invalid headers.
558 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
559 fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
560
561 // Hide Accept header normally added by default.
562 fetcher->SetHeader("Accept", "");
563
564 PythonHttpServer server;
565 int port = server.GetPort();
566 ASSERT_TRUE(server.started_);
567
Alex Deymo2c131bb2016-05-26 16:43:13 -0700568 this->loop_.PostTask(
569 FROM_HERE,
570 base::Bind(StartTransfer,
571 fetcher.get(),
572 LocalServerUrlForPath(port, "/echo-headers")));
Alex Deymofdd6dec2016-03-03 22:35:43 -0800573 this->loop_.Run();
574
575 EXPECT_NE(string::npos,
576 delegate.data.find("user-agent: Override that header\r\n"));
577 EXPECT_NE(string::npos,
578 delegate.data.find("Authorization: Basic user:passwd\r\n"));
579
580 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
581 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
582 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
583}
584
rspangler@google.com49fdf182009-10-10 00:57:34 +0000585namespace {
586class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
587 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700588 bool ReceivedBytes(HttpFetcher* fetcher,
589 const void* /* bytes */,
590 size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000591 CHECK(!paused_);
592 paused_ = true;
593 fetcher->Pause();
Amin Hassani0cd9d772018-07-31 23:55:43 -0700594 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000595 }
Alex Deymo610277e2014-11-11 21:18:11 -0800596 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700597 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000598 }
Amin Hassanib2689592019-01-13 17:04:28 -0800599 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000600 void Unpause() {
601 CHECK(paused_);
602 paused_ = false;
603 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000604 }
605 bool paused_;
606 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000607};
608
Alex Deymo60ca1a72015-06-18 18:19:15 -0700609void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
610 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000611 if (delegate->paused_)
612 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700613 // Update the task id with the new scheduled callback.
614 *my_id = MessageLoop::current()->PostDelayedTask(
615 FROM_HERE,
616 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
617 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000618}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700619} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000620
621TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800622 PausingHttpFetcherTestDelegate delegate;
623 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
624 delegate.paused_ = false;
625 delegate.fetcher_ = fetcher.get();
626 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000627
Alex Deymof2858572016-02-25 11:20:13 -0800628 unique_ptr<HttpServer> server(this->test_.CreateServer());
629 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800630
Alex Deymof2858572016-02-25 11:20:13 -0800631 MessageLoop::TaskId callback_id;
632 callback_id = this->loop_.PostDelayedTask(
633 FROM_HERE,
634 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
635 base::TimeDelta::FromMilliseconds(200));
636 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000637
Alex Deymof2858572016-02-25 11:20:13 -0800638 this->loop_.Run();
639 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
640}
641
642// This test will pause the fetcher while the download is not yet started
643// because it is waiting for the proxy to be resolved.
644TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700645 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymof2858572016-02-25 11:20:13 -0800646 return;
647 MockProxyResolver mock_resolver;
648 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
649
650 // Saved arguments from the proxy call.
Alex Deymo35821942017-02-05 04:36:02 +0000651 ProxiesResolvedFn proxy_callback;
652 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _))
653 .WillOnce(DoAll(SaveArg<1>(&proxy_callback), Return(true)));
Alex Deymof2858572016-02-25 11:20:13 -0800654 fetcher->BeginTransfer("http://fake_url");
655 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
656
657 // Pausing and unpausing while resolving the proxy should not affect anything.
658 fetcher->Pause();
659 fetcher->Unpause();
660 fetcher->Pause();
661 // Proxy resolver comes back after we paused the fetcher.
Alex Deymoc00ec562017-02-05 04:36:02 +0000662 ASSERT_FALSE(proxy_callback.is_null());
Alex Deymo35821942017-02-05 04:36:02 +0000663 proxy_callback.Run({1, kNoProxy});
rspangler@google.com49fdf182009-10-10 00:57:34 +0000664}
665
666namespace {
667class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
668 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700669 bool ReceivedBytes(HttpFetcher* fetcher,
670 const void* bytes,
671 size_t length) override {
672 return true;
673 }
Alex Deymo610277e2014-11-11 21:18:11 -0800674 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800675 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700676 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000677 }
Alex Deymo610277e2014-11-11 21:18:11 -0800678 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800679 EXPECT_EQ(fetcher, fetcher_.get());
680 EXPECT_FALSE(once_);
681 EXPECT_TRUE(callback_once_);
682 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700683 // The fetcher could have a callback scheduled on the ProxyResolver that
684 // can fire after this callback. We wait until the end of the test to
685 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800686 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000687 void TerminateTransfer() {
688 CHECK(once_);
689 once_ = false;
690 fetcher_->TerminateTransfer();
691 }
Amin Hassanib2689592019-01-13 17:04:28 -0800692 void EndLoop() { MessageLoop::current()->BreakLoop(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000693 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800694 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700695 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000696};
697
Alex Deymo60ca1a72015-06-18 18:19:15 -0700698void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
699 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000700 if (delegate->once_) {
701 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700702 *my_id = MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800703 FROM_HERE, base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000704 } else {
705 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700706 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000707 }
708}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700709} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000710
711TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700712 AbortingHttpFetcherTestDelegate delegate;
713 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
714 delegate.once_ = true;
715 delegate.callback_once_ = true;
716 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000717
Alex Deymo60ca1a72015-06-18 18:19:15 -0700718 unique_ptr<HttpServer> server(this->test_.CreateServer());
719 this->test_.IgnoreServerAborting(server.get());
720 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800721
Alex Deymo60ca1a72015-06-18 18:19:15 -0700722 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000723
Alex Deymo60ca1a72015-06-18 18:19:15 -0700724 task_id = this->loop_.PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800725 FROM_HERE, base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700726 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
727
728 this->loop_.Run();
729 CHECK(!delegate.once_);
730 CHECK(!delegate.callback_once_);
731 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000732}
733
Alex Deymo71f67622017-02-03 21:30:24 -0800734TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
735 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
736 return;
737 MockProxyResolver mock_resolver;
738 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
739
740 HttpFetcherTestDelegate delegate;
741 fetcher->set_delegate(&delegate);
742
743 EXPECT_CALL(mock_resolver, GetProxiesForUrl(_, _)).WillOnce(Return(123));
744 fetcher->BeginTransfer("http://fake_url");
745 // Run the message loop until idle. This must call the MockProxyResolver with
746 // the request.
747 while (this->loop_.RunOnce(false)) {
748 }
749 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
750
751 EXPECT_CALL(mock_resolver, CancelProxyRequest(123)).WillOnce(Return(true));
752
753 // Terminate the transfer right before the proxy resolution response.
754 fetcher->TerminateTransfer();
755 EXPECT_EQ(0, delegate.times_received_bytes_called_);
756 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
757 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
758}
759
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000760namespace {
761class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
762 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700763 bool ReceivedBytes(HttpFetcher* fetcher,
764 const void* bytes,
765 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800766 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700767 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000768 }
Alex Deymo610277e2014-11-11 21:18:11 -0800769 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700770 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800771 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700772 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000773 }
Amin Hassanib2689592019-01-13 17:04:28 -0800774 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000775 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000776};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700777} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000778
779TYPED_TEST(HttpFetcherTest, FlakyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700780 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000781 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000782 {
783 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700784 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000785 fetcher->set_delegate(&delegate);
786
Ben Chan02f7c1d2014-10-18 15:18:02 -0700787 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800788 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000789
Amin Hassanib2689592019-01-13 17:04:28 -0800790 this->loop_.PostTask(FROM_HERE,
791 base::Bind(&StartTransfer,
792 fetcher.get(),
793 LocalServerUrlForPath(
794 server->GetPort(),
795 base::StringPrintf("/flaky/%d/%d/%d/%d",
796 kBigLength,
797 kFlakyTruncateLength,
798 kFlakySleepEvery,
799 kFlakySleepSecs))));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700800 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000801
802 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800803 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800804 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000805 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
806 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
807 }
808 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000809}
810
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700811namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700812// This delegate kills the server attached to it after receiving any bytes.
813// This can be used for testing what happens when you try to fetch data and
814// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700815class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
816 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700817 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700818 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700819
Alex Deymo610277e2014-11-11 21:18:11 -0800820 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700821 if (server_) {
822 LOG(INFO) << "Stopping server in destructor";
Alex Deymob20de692017-02-05 07:47:37 +0000823 server_.reset();
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700824 LOG(INFO) << "server stopped";
825 }
826 }
827
Amin Hassani0cd9d772018-07-31 23:55:43 -0700828 bool ReceivedBytes(HttpFetcher* fetcher,
829 const void* bytes,
830 size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700831 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700832 LOG(INFO) << "Stopping server in ReceivedBytes";
Alex Deymob20de692017-02-05 07:47:37 +0000833 server_.reset();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700834 LOG(INFO) << "server stopped";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700835 }
Amin Hassani0cd9d772018-07-31 23:55:43 -0700836 return true;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700837 }
Alex Deymo610277e2014-11-11 21:18:11 -0800838 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700839 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700840 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymob20de692017-02-05 07:47:37 +0000841 times_transfer_complete_called_++;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700842 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700843 }
Alex Deymo610277e2014-11-11 21:18:11 -0800844 void TransferTerminated(HttpFetcher* fetcher) override {
Alex Deymob20de692017-02-05 07:47:37 +0000845 times_transfer_terminated_called_++;
846 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800847 }
Alex Deymob20de692017-02-05 07:47:37 +0000848 unique_ptr<PythonHttpServer> server_;
849 int times_transfer_terminated_called_{0};
850 int times_transfer_complete_called_{0};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700851};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700852} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700853
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700854TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700855 // This test ensures that a fetcher responds correctly when a server isn't
856 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800857 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700858 return;
Alex Deymob20de692017-02-05 07:47:37 +0000859 FailureHttpFetcherTestDelegate delegate(nullptr);
860 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
861 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700862
Alex Deymob20de692017-02-05 07:47:37 +0000863 this->loop_.PostTask(
864 FROM_HERE,
865 base::Bind(
866 StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
867 this->loop_.Run();
868 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
869 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700870
Alex Deymob20de692017-02-05 07:47:37 +0000871 // Exiting and testing happens in the delegate
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700872}
873
Alex Deymof123ae22015-09-24 14:59:43 -0700874TYPED_TEST(HttpFetcherTest, NoResponseTest) {
875 // This test starts a new http server but the server doesn't respond and just
876 // closes the connection.
877 if (this->test_.IsMock())
878 return;
879
880 PythonHttpServer* server = new PythonHttpServer();
881 int port = server->GetPort();
882 ASSERT_TRUE(server->started_);
883
884 // Handles destruction and claims ownership.
885 FailureHttpFetcherTestDelegate delegate(server);
886 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
887 fetcher->set_delegate(&delegate);
888 // The server will not reply at all, so we can limit the execution time of the
889 // test by reducing the low-speed timeout to something small. The test will
890 // finish once the TimeoutCallback() triggers (every second) and the timeout
891 // expired.
892 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
893
Amin Hassanib2689592019-01-13 17:04:28 -0800894 this->loop_.PostTask(
895 FROM_HERE,
896 base::Bind(
897 StartTransfer, fetcher.get(), LocalServerUrlForPath(port, "/hang")));
Alex Deymof123ae22015-09-24 14:59:43 -0700898 this->loop_.Run();
Alex Deymob20de692017-02-05 07:47:37 +0000899 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
900 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Alex Deymof123ae22015-09-24 14:59:43 -0700901
902 // Check that no other callback runs in the next two seconds. That would
903 // indicate a leaked callback.
904 bool timeout = false;
Luis Hector Chavezf1cf3482016-07-19 14:29:19 -0700905 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
906 base::Unretained(&timeout));
Amin Hassanib2689592019-01-13 17:04:28 -0800907 this->loop_.PostDelayedTask(
908 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
Alex Deymof123ae22015-09-24 14:59:43 -0700909 EXPECT_TRUE(this->loop_.RunOnce(true));
910 EXPECT_TRUE(timeout);
911}
912
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700913TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700914 // This test starts a new http server and kills it after receiving its first
915 // set of bytes. It test whether or not our fetcher eventually gives up on
916 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800917 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700918 return;
Alex Deymob20de692017-02-05 07:47:37 +0000919 PythonHttpServer* server = new PythonHttpServer();
920 int port = server->GetPort();
921 ASSERT_TRUE(server->started_);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700922
Alex Deymob20de692017-02-05 07:47:37 +0000923 // Handles destruction and claims ownership.
924 FailureHttpFetcherTestDelegate delegate(server);
925 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
926 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700927
Alex Deymob20de692017-02-05 07:47:37 +0000928 this->loop_.PostTask(
929 FROM_HERE,
930 base::Bind(StartTransfer,
931 fetcher.get(),
932 LocalServerUrlForPath(port,
933 base::StringPrintf("/flaky/%d/%d/%d/%d",
934 kBigLength,
935 kFlakyTruncateLength,
936 kFlakySleepEvery,
937 kFlakySleepSecs))));
938 this->loop_.Run();
939 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
940 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700941
Alex Deymob20de692017-02-05 07:47:37 +0000942 // Exiting and testing happens in the delegate
943}
944
945// Test that we can cancel a transfer while it is still trying to connect to the
946// server. This test kills the server after a few bytes are received.
947TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
948 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
949 return;
950
951 PythonHttpServer* server = new PythonHttpServer();
952 int port = server->GetPort();
953 ASSERT_TRUE(server->started_);
954
955 // Handles destruction and claims ownership.
956 FailureHttpFetcherTestDelegate delegate(server);
957 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
958 fetcher->set_delegate(&delegate);
959
960 this->loop_.PostTask(
961 FROM_HERE,
962 base::Bind(StartTransfer,
963 fetcher.get(),
964 LocalServerUrlForPath(port,
965 base::StringPrintf("/flaky/%d/%d/%d/%d",
966 kBigLength,
967 kFlakyTruncateLength,
968 kFlakySleepEvery,
969 kFlakySleepSecs))));
970 // Terminating the transfer after 3 seconds gives it a chance to contact the
971 // server and enter the retry loop.
972 this->loop_.PostDelayedTask(FROM_HERE,
973 base::Bind(&HttpFetcher::TerminateTransfer,
974 base::Unretained(fetcher.get())),
975 base::TimeDelta::FromSeconds(3));
976
977 // Exiting and testing happens in the delegate.
978 this->loop_.Run();
979 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
980 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
981
982 // Check that no other callback runs in the next two seconds. That would
983 // indicate a leaked callback.
984 bool timeout = false;
985 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
986 base::Unretained(&timeout));
987 this->loop_.PostDelayedTask(
988 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
989 EXPECT_TRUE(this->loop_.RunOnce(true));
990 EXPECT_TRUE(timeout);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700991}
992
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700993namespace {
Amin Hassanib2689592019-01-13 17:04:28 -0800994const HttpResponseCode kRedirectCodes[] = {kHttpResponseMovedPermanently,
995 kHttpResponseFound,
996 kHttpResponseSeeOther,
997 kHttpResponseTempRedirect};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700998
999class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
1000 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001001 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001002 : expected_successful_(expected_successful) {}
Amin Hassani0cd9d772018-07-31 23:55:43 -07001003 bool ReceivedBytes(HttpFetcher* fetcher,
1004 const void* bytes,
1005 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001006 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001007 return true;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001008 }
Alex Deymo610277e2014-11-11 21:18:11 -08001009 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001010 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001011 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001012 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001013 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001014 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
1015 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -07001016 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001017 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001018 }
Amin Hassanib2689592019-01-13 17:04:28 -08001019 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001020 bool expected_successful_;
1021 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001022};
1023
1024// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001025void RedirectTest(const HttpServer* server,
1026 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001027 const string& url,
1028 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001029 RedirectHttpFetcherTestDelegate delegate(expected_successful);
1030 unique_ptr<HttpFetcher> fetcher(http_fetcher);
1031 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001032
Amin Hassanib2689592019-01-13 17:04:28 -08001033 MessageLoop::current()->PostTask(
1034 FROM_HERE,
1035 base::Bind(StartTransfer,
1036 fetcher.get(),
1037 LocalServerUrlForPath(server->GetPort(), url)));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001038 MessageLoop::current()->Run();
1039 if (expected_successful) {
1040 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -08001041 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -07001042 for (int i = 0; i < kMediumLength; i += 10) {
1043 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
1044 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001045 }
1046 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001047}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001048} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001049
1050TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001051 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001052 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001053
Ben Chan02f7c1d2014-10-18 15:18:02 -07001054 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001055 ASSERT_TRUE(server->started_);
1056
hscham00b6aa22020-02-20 12:32:06 +09001057 for (size_t c = 0; c < base::size(kRedirectCodes); ++c) {
Amin Hassanib2689592019-01-13 17:04:28 -08001058 const string url = base::StringPrintf(
1059 "/redirect/%d/download/%d", kRedirectCodes[c], kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001060 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001061 }
1062}
1063
1064TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001065 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001066 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001067
Ben Chan02f7c1d2014-10-18 15:18:02 -07001068 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001069 ASSERT_TRUE(server->started_);
1070
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001071 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001072 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001073 url += base::StringPrintf("/redirect/%d",
hscham00b6aa22020-02-20 12:32:06 +09001074 kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001075 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001076 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001077 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001078}
1079
1080TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001081 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001082 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001083
Ben Chan02f7c1d2014-10-18 15:18:02 -07001084 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001085 ASSERT_TRUE(server->started_);
1086
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001087 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001088 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001089 url += base::StringPrintf("/redirect/%d",
hscham00b6aa22020-02-20 12:32:06 +09001090 kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001091 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001092 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001093 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001094}
1095
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001096namespace {
1097class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1098 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001099 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001100 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001101
Amin Hassani0cd9d772018-07-31 23:55:43 -07001102 bool ReceivedBytes(HttpFetcher* fetcher,
1103 const void* bytes,
1104 size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001105 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001106 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001107 return true;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001108 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001109
Alex Deymo610277e2014-11-11 21:18:11 -08001110 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001111 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001112 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001113 if (expected_response_code_ != 0)
1114 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001115 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -07001116 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001117 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001118 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001119
Amin Hassanib2689592019-01-13 17:04:28 -08001120 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001121
Ben Chan02f7c1d2014-10-18 15:18:02 -07001122 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001123 int expected_response_code_;
1124 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001125};
1126
1127void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -03001128 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001129 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -07001130 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001131 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -08001132 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001133 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001134 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1135 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001136
Alex Deymo60ca1a72015-06-18 18:19:15 -07001137 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -08001138 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001139 ASSERT_TRUE(multi_fetcher);
1140 multi_fetcher->ClearRanges();
1141 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
Amin Hassanib2689592019-01-13 17:04:28 -08001142 e = ranges.end();
1143 it != e;
1144 ++it) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001145 string tmp_str = base::StringPrintf("%jd+", it->first);
1146 if (it->second > 0) {
1147 base::StringAppendF(&tmp_str, "%jd", it->second);
1148 multi_fetcher->AddRange(it->first, it->second);
1149 } else {
1150 base::StringAppendF(&tmp_str, "?");
1151 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001152 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001153 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001154 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001155 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001156 multi_fetcher->set_delegate(&delegate);
1157
1158 MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -08001159 FROM_HERE, base::Bind(StartTransfer, multi_fetcher, url));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001160 MessageLoop::current()->Run();
1161
1162 EXPECT_EQ(expected_size, delegate.data.size());
1163 EXPECT_EQ(expected_prefix,
1164 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001165}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001166} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001167
Darin Petkov9ce452b2010-11-17 14:33:28 -08001168TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001169 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001170 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001171
Ben Chan02f7c1d2014-10-18 15:18:02 -07001172 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001173 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001174
Ben Chanf9cb98c2014-09-21 18:31:30 -07001175 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001176 ranges.push_back(make_pair(0, 25));
Tao Bao642b32b2019-01-02 15:33:42 -08001177 ranges.push_back(make_pair(99, 17));
1178 MultiTest(this->test_.NewLargeFetcher(),
1179 this->test_.fake_hardware(),
1180 this->test_.BigUrl(server->GetPort()),
1181 ranges,
1182 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1183 25 + 17,
1184 this->test_.IsFileFetcher() ? kHttpResponseOk
1185 : kHttpResponsePartialContent);
1186}
1187
1188TYPED_TEST(HttpFetcherTest, MultiHttpFetcherUnspecifiedEndTest) {
1189 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1190 return;
1191
1192 unique_ptr<HttpServer> server(this->test_.CreateServer());
1193 ASSERT_TRUE(server->started_);
1194
1195 vector<pair<off_t, off_t>> ranges;
1196 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001197 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001198 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001199 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001200 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001201 ranges,
1202 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001203 kBigLength - (99 - 25),
1204 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001205}
1206
1207TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001208 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001209 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001210
Ben Chan02f7c1d2014-10-18 15:18:02 -07001211 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001212 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001213
Ben Chanf9cb98c2014-09-21 18:31:30 -07001214 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001215 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001216 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001217 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001218 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001219 ranges,
1220 "abcdefghijabcdefghijabcd",
1221 24,
Tao Bao642b32b2019-01-02 15:33:42 -08001222 this->test_.IsFileFetcher() ? kHttpResponseOk
1223 : kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001224}
1225
1226TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001227 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001228 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001229
Ben Chan02f7c1d2014-10-18 15:18:02 -07001230 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001231 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001232
Ben Chanf9cb98c2014-09-21 18:31:30 -07001233 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001234 ranges.push_back(make_pair(kBigLength - 2, 0));
1235 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001236 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001237 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001238 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001239 ranges,
1240 "ijhij",
1241 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001242 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001243}
1244
1245TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001246 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001247 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001248
Ben Chan02f7c1d2014-10-18 15:18:02 -07001249 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001250 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001251
Ben Chanf9cb98c2014-09-21 18:31:30 -07001252 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001253 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001254 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001255 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001256 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001257 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001258 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001259 ranges,
1260 "ij",
1261 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001262 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001263 ranges.push_back(make_pair(0, 5));
1264 }
1265}
1266
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001267// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1268// should retry with other proxies listed before giving up.
1269//
1270// (1) successful recovery: The offset fetch will fail twice but succeed with
1271// the third proxy.
1272TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001273 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001274 return;
1275
Ben Chan02f7c1d2014-10-18 15:18:02 -07001276 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001277 ASSERT_TRUE(server->started_);
1278
Ben Chanf9cb98c2014-09-21 18:31:30 -07001279 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001280 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001281 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001282 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001283 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001284 LocalServerUrlForPath(
1285 server->GetPort(),
1286 base::StringPrintf("/error-if-offset/%d/2", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001287 ranges,
1288 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1289 kBigLength - (99 - 25),
1290 kHttpResponsePartialContent);
1291}
1292
1293// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1294// fetcher will signal a (failed) completed transfer to the delegate.
1295TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001296 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001297 return;
1298
Ben Chan02f7c1d2014-10-18 15:18:02 -07001299 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001300 ASSERT_TRUE(server->started_);
1301
Ben Chanf9cb98c2014-09-21 18:31:30 -07001302 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001303 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001304 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001305 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001306 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001307 LocalServerUrlForPath(
1308 server->GetPort(),
1309 base::StringPrintf("/error-if-offset/%d/3", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001310 ranges,
1311 "abcdefghijabcdefghijabcde", // only received the first chunk
1312 25,
1313 kHttpResponseUndefined);
1314}
1315
Alex Deymo4ea2d922017-02-05 07:35:32 +00001316namespace {
1317// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1318class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1319 public:
1320 explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1321 : terminate_trigger_bytes_(terminate_trigger_bytes) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001322
Amin Hassani0cd9d772018-07-31 23:55:43 -07001323 bool ReceivedBytes(HttpFetcher* fetcher,
Alex Deymo4ea2d922017-02-05 07:35:32 +00001324 const void* bytes,
1325 size_t length) override {
1326 LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
1327 EXPECT_EQ(fetcher, fetcher_.get());
Tao Bao642b32b2019-01-02 15:33:42 -08001328 bool should_terminate = false;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001329 if (bytes_downloaded_ < terminate_trigger_bytes_ &&
1330 bytes_downloaded_ + length >= terminate_trigger_bytes_) {
1331 MessageLoop::current()->PostTask(
1332 FROM_HERE,
1333 base::Bind(&HttpFetcher::TerminateTransfer,
1334 base::Unretained(fetcher_.get())));
Tao Bao642b32b2019-01-02 15:33:42 -08001335 should_terminate = true;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001336 }
1337 bytes_downloaded_ += length;
Tao Bao642b32b2019-01-02 15:33:42 -08001338 return !should_terminate;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001339 }
1340
1341 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1342 ADD_FAILURE() << "TransferComplete called but expected a failure";
1343 // Destroy the fetcher (because we're allowed to).
1344 fetcher_.reset(nullptr);
1345 MessageLoop::current()->BreakLoop();
1346 }
1347
1348 void TransferTerminated(HttpFetcher* fetcher) override {
1349 // Destroy the fetcher (because we're allowed to).
1350 fetcher_.reset(nullptr);
1351 MessageLoop::current()->BreakLoop();
1352 }
1353
1354 unique_ptr<HttpFetcher> fetcher_;
1355 size_t bytes_downloaded_{0};
1356 size_t terminate_trigger_bytes_;
1357};
1358} // namespace
1359
1360TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
1361 if (!this->test_.IsMulti())
1362 return;
1363 const size_t kRangeTrigger = 1000;
1364 MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
1365
1366 unique_ptr<HttpServer> server(this->test_.CreateServer());
1367 ASSERT_TRUE(server->started_);
1368
1369 MultiRangeHttpFetcher* multi_fetcher =
1370 static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
1371 ASSERT_TRUE(multi_fetcher);
1372 // Transfer ownership of the fetcher to the delegate.
1373 delegate.fetcher_.reset(multi_fetcher);
1374 multi_fetcher->set_delegate(&delegate);
1375
1376 multi_fetcher->ClearRanges();
1377 multi_fetcher->AddRange(45, kRangeTrigger);
1378 multi_fetcher->AddRange(2000, 100);
1379
1380 this->test_.fake_hardware()->SetIsOfficialBuild(false);
1381
1382 StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
1383 MessageLoop::current()->Run();
1384
1385 // Check that the delegate made it to the trigger point.
1386 EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
1387}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001388
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001389namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001390class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001391 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -07001392 bool ReceivedBytes(HttpFetcher* fetcher,
1393 const void* bytes,
1394 size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001395 ADD_FAILURE();
Amin Hassani0cd9d772018-07-31 23:55:43 -07001396 return true;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001397 }
Alex Deymo610277e2014-11-11 21:18:11 -08001398 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001399 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001400 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001401 }
Amin Hassanib2689592019-01-13 17:04:28 -08001402 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001403};
1404
Alex Deymo60ca1a72015-06-18 18:19:15 -07001405void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1406 bool is_official_build) {
1407 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1408 return;
1409
1410 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1411 ASSERT_TRUE(server->started_);
1412
1413 BlockedTransferTestDelegate delegate;
1414 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1415 LOG(INFO) << "is_official_build: " << is_official_build;
1416 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001417 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001418 fetcher->set_delegate(&delegate);
1419
Amin Hassanib2689592019-01-13 17:04:28 -08001420 MessageLoop::current()->PostTask(
1421 FROM_HERE,
1422 base::Bind(
1423 StartTransfer,
1424 fetcher.get(),
1425 LocalServerUrlForPath(server->GetPort(),
1426 fetcher_test->SmallUrl(server->GetPort()))));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001427 MessageLoop::current()->Run();
1428}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001429} // namespace
1430
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001431TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001432 BlockedTransferTestHelper(&this->test_, false);
1433}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001434
Alex Deymo60ca1a72015-06-18 18:19:15 -07001435TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1436 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001437}
1438
rspangler@google.com49fdf182009-10-10 00:57:34 +00001439} // namespace chromeos_update_engine