blob: 589579e313f221b7715259f2cf8ed97c9bdfcc5e [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>
40#include <brillo/process.h>
41#include <brillo/streams/file_stream.h>
42#include <brillo/streams/stream.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080043#include <gtest/gtest.h>
44
Alex Deymoc1c17b42015-11-23 03:53:15 -030045#include "update_engine/common/fake_hardware.h"
Alex Deymo2c131bb2016-05-26 16:43:13 -070046#include "update_engine/common/file_fetcher.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080047#include "update_engine/common/http_common.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080048#include "update_engine/common/mock_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070049#include "update_engine/common/mock_proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080050#include "update_engine/common/multi_range_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070051#include "update_engine/common/proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080052#include "update_engine/common/test_utils.h"
53#include "update_engine/common/utils.h"
Alex Deymo14c0da82016-07-20 16:45:45 -070054#include "update_engine/libcurl_http_fetcher.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000055
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070056using brillo::MessageLoop;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070057using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080058using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000059using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070060using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000061using std::vector;
Amin Hassanib2689592019-01-13 17:04:28 -080062using testing::_;
Alex Deymof2858572016-02-25 11:20:13 -080063using testing::DoAll;
64using testing::Return;
65using testing::SaveArg;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000066
Gilad Arnold9bedeb52011-11-17 16:19:57 -080067namespace {
68
Amin Hassanib2689592019-01-13 17:04:28 -080069const int kBigLength = 100000;
70const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080071const int kFlakyTruncateLength = 29000;
Amin Hassanib2689592019-01-13 17:04:28 -080072const int kFlakySleepEvery = 3;
73const int kFlakySleepSecs = 10;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080074
75} // namespace
76
rspangler@google.com49fdf182009-10-10 00:57:34 +000077namespace chromeos_update_engine {
78
Amin Hassanib2689592019-01-13 17:04:28 -080079static const char* kUnusedUrl = "unused://unused";
Gilad Arnold9bedeb52011-11-17 16:19:57 -080080
Amin Hassanib2689592019-01-13 17:04:28 -080081static inline string LocalServerUrlForPath(in_port_t port, const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070082 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Amin Hassanib2689592019-01-13 17:04:28 -080083 return base::StringPrintf(
84 "http://127.0.0.1%s%s", port_str.c_str(), path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000085}
86
Gilad Arnold9bedeb52011-11-17 16:19:57 -080087//
88// Class hierarchy for HTTP server implementations.
89//
90
91class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000092 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080093 // This makes it an abstract class (dirty but works).
94 virtual ~HttpServer() = 0;
95
Amin Hassanib2689592019-01-13 17:04:28 -080096 virtual in_port_t GetPort() const { return 0; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070097
rspangler@google.com49fdf182009-10-10 00:57:34 +000098 bool started_;
99};
100
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800101HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000102
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800103class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000104 public:
Amin Hassanib2689592019-01-13 17:04:28 -0800105 NullHttpServer() { started_ = true; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000106};
107
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800108class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000109 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700110 PythonHttpServer() : port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000111 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700112
113 // Spawn the server process.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700114 unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
Sen Jiang260f03b2016-03-21 15:34:58 -0700115 http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
Alex Deymo535f3b72015-08-07 10:51:32 -0700116 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
117
118 if (!http_server->Start()) {
119 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000120 return;
121 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700122 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700123
124 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700125 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700126 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
127 if (!stdout)
128 return;
129
130 vector<char> buf(128);
131 string line;
132 while (line.find('\n') == string::npos) {
133 size_t read;
134 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
135 ADD_FAILURE() << "error reading http server stdout";
136 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700137 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700138 line.append(buf.data(), read);
139 if (read == 0)
140 break;
141 }
142 // Parse the port from the output line.
143 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
144 if (line.size() < listening_msg_prefix_len) {
145 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700146 return;
147 }
148
Alex Deymo535f3b72015-08-07 10:51:32 -0700149 EXPECT_EQ(kServerListeningMsgPrefix,
150 line.substr(0, listening_msg_prefix_len));
151 string port_str = line.substr(listening_msg_prefix_len);
152 port_str.resize(port_str.find('\n'));
153 EXPECT_TRUE(base::StringToUint(port_str, &port_));
154
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700155 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700156 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700157
158 // Any failure before this point will SIGKILL the test server if started
159 // when the |http_server| goes out of scope.
160 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000161 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800162
rspangler@google.com49fdf182009-10-10 00:57:34 +0000163 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700164 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700165 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000166 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700167 // Wait up to 10 seconds for the process to finish. Destroying the process
168 // will kill it with a SIGKILL otherwise.
169 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000170 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800171
Amin Hassanib2689592019-01-13 17:04:28 -0800172 in_port_t GetPort() const override { return port_; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700173
174 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700175 static const char* kServerListeningMsgPrefix;
176
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700177 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700178 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000179};
180
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700181const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
182
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800183//
184// Class hierarchy for HTTP fetcher test wrappers.
185//
186
187class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000188 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700189 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700190 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700191
Alex Deymof2858572016-02-25 11:20:13 -0800192 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
193 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
194 proxy_resolver_.set_num_proxies(num_proxies);
195 return NewLargeFetcher(&proxy_resolver_);
196 }
Amin Hassanib2689592019-01-13 17:04:28 -0800197 HttpFetcher* NewLargeFetcher() { return NewLargeFetcher(1); }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800198
Alex Deymof2858572016-02-25 11:20:13 -0800199 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800200 HttpFetcher* NewSmallFetcher() {
Alex Deymof2858572016-02-25 11:20:13 -0800201 proxy_resolver_.set_num_proxies(1);
202 return NewSmallFetcher(&proxy_resolver_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800203 }
204
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700205 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
206 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
207 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800208
209 virtual bool IsMock() const = 0;
210 virtual bool IsMulti() const = 0;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700211 virtual bool IsHttpSupported() const = 0;
Tao Bao642b32b2019-01-02 15:33:42 -0800212 virtual bool IsFileFetcher() const = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800213
214 virtual void IgnoreServerAborting(HttpServer* server) const {}
215
Alex Deymo60ca1a72015-06-18 18:19:15 -0700216 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800217
Amin Hassanib2689592019-01-13 17:04:28 -0800218 FakeHardware* fake_hardware() { return &fake_hardware_; }
Alex Deymoc1c17b42015-11-23 03:53:15 -0300219
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800220 protected:
221 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300222 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800223};
224
225class MockHttpFetcherTest : public AnyHttpFetcherTest {
226 public:
227 // Necessary to unhide the definition in the base class.
228 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800229 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700230 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800231 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800232 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800233 }
234
235 // Necessary to unhide the definition in the base class.
236 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800237 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
238 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800239 }
240
Alex Deymo610277e2014-11-11 21:18:11 -0800241 bool IsMock() const override { return true; }
242 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700243 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800244 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800245
Amin Hassanib2689592019-01-13 17:04:28 -0800246 HttpServer* CreateServer() override { return new NullHttpServer; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800247};
248
249class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
250 public:
251 // Necessary to unhide the definition in the base class.
252 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800253 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
254 LibcurlHttpFetcher* ret =
255 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700256 // Speed up test execution.
257 ret->set_idle_seconds(1);
258 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300259 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000260 return ret;
261 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800262
263 // Necessary to unhide the definition in the base class.
264 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800265 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
266 return NewLargeFetcher(proxy_resolver);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000267 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800268
Alex Deymo610277e2014-11-11 21:18:11 -0800269 string BigUrl(in_port_t port) const override {
Amin Hassanib2689592019-01-13 17:04:28 -0800270 return LocalServerUrlForPath(
271 port, base::StringPrintf("/download/%d", kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000272 }
Alex Deymo610277e2014-11-11 21:18:11 -0800273 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700274 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000275 }
Alex Deymo610277e2014-11-11 21:18:11 -0800276 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700277 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800278 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800279
Alex Deymo610277e2014-11-11 21:18:11 -0800280 bool IsMock() const override { return false; }
281 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700282 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800283 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800284
Alex Deymo610277e2014-11-11 21:18:11 -0800285 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700286 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700287 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800288
Amin Hassanib2689592019-01-13 17:04:28 -0800289 HttpServer* CreateServer() override { return new PythonHttpServer; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000290};
291
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800292class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700293 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800294 // Necessary to unhide the definition in the base class.
295 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800296 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
297 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
298 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800299 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800300 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700301 // Speed up test execution.
302 ret->set_idle_seconds(1);
303 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300304 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700305 return ret;
306 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800307
308 // Necessary to unhide the definition in the base class.
309 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800310 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
311 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800312 }
313
Alex Deymo610277e2014-11-11 21:18:11 -0800314 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700315};
316
Alex Deymo2c131bb2016-05-26 16:43:13 -0700317class FileFetcherTest : public AnyHttpFetcherTest {
318 public:
319 // Necessary to unhide the definition in the base class.
320 using AnyHttpFetcherTest::NewLargeFetcher;
321 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
322 return new FileFetcher();
323 }
324
325 // Necessary to unhide the definition in the base class.
326 using AnyHttpFetcherTest::NewSmallFetcher;
327 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
328 return NewLargeFetcher(proxy_resolver);
329 }
330
331 string BigUrl(in_port_t port) const override {
Tao Bao642b32b2019-01-02 15:33:42 -0800332 static string big_contents = []() {
333 string buf;
334 buf.reserve(kBigLength);
335 constexpr const char* kBigUrlContent = "abcdefghij";
336 for (size_t i = 0; i < kBigLength; i += strlen(kBigUrlContent)) {
337 buf.append(kBigUrlContent,
338 std::min(kBigLength - i, strlen(kBigUrlContent)));
339 }
340 return buf;
341 }();
342 test_utils::WriteFileString(temp_file_.path(), big_contents);
Alex Deymo2c131bb2016-05-26 16:43:13 -0700343 return "file://" + temp_file_.path();
344 }
345 string SmallUrl(in_port_t port) const override {
346 test_utils::WriteFileString(temp_file_.path(), "small contents");
347 return "file://" + temp_file_.path();
348 }
349 string ErrorUrl(in_port_t port) const override {
350 return "file:///path/to/non-existing-file";
351 }
352
353 bool IsMock() const override { return false; }
354 bool IsMulti() const override { return false; }
355 bool IsHttpSupported() const override { return false; }
Tao Bao642b32b2019-01-02 15:33:42 -0800356 bool IsFileFetcher() const override { return true; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700357
358 void IgnoreServerAborting(HttpServer* server) const override {}
359
360 HttpServer* CreateServer() override { return new NullHttpServer; }
361
362 private:
363 test_utils::ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
364};
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800365
Tao Bao642b32b2019-01-02 15:33:42 -0800366class MultiRangeHttpFetcherOverFileFetcherTest : public FileFetcherTest {
367 public:
368 // Necessary to unhide the definition in the base class.
369 using AnyHttpFetcherTest::NewLargeFetcher;
370 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
371 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(new FileFetcher());
372 ret->ClearRanges();
373 // FileFetcher doesn't support range with unspecified length.
374 ret->AddRange(0, 1);
375 // Speed up test execution.
376 ret->set_idle_seconds(1);
377 ret->set_retry_seconds(1);
378 fake_hardware_.SetIsOfficialBuild(false);
379 return ret;
380 }
381
382 // Necessary to unhide the definition in the base class.
383 using AnyHttpFetcherTest::NewSmallFetcher;
384 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
385 return NewLargeFetcher(proxy_resolver);
386 }
387
388 bool IsMulti() const override { return true; }
389};
390
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800391//
392// Infrastructure for type tests of HTTP fetcher.
393// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
394//
395
396// Fixture class template. We use an explicit constraint to guarantee that it
397// can only be instantiated with an AnyHttpFetcherTest type, see:
398// http://www2.research.att.com/~bs/bs_faq2.html#constraints
399template <typename T>
400class HttpFetcherTest : public ::testing::Test {
401 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700402 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700403 brillo::BaseMessageLoop loop_{&base_loop_};
Alex Deymo60ca1a72015-06-18 18:19:15 -0700404
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800405 T test_;
406
Alex Deymo60ca1a72015-06-18 18:19:15 -0700407 protected:
Amin Hassanib2689592019-01-13 17:04:28 -0800408 HttpFetcherTest() { loop_.SetAsCurrent(); }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700409
410 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700411 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700412 }
413
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800414 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700415 static void TypeConstraint(T* a) {
Amin Hassanib2689592019-01-13 17:04:28 -0800416 AnyHttpFetcherTest* b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700417 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700418 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800419 }
420};
421
422// Test case types list.
423typedef ::testing::Types<LibcurlHttpFetcherTest,
424 MockHttpFetcherTest,
Alex Deymo2c131bb2016-05-26 16:43:13 -0700425 MultiRangeHttpFetcherTest,
Tao Bao642b32b2019-01-02 15:33:42 -0800426 FileFetcherTest,
427 MultiRangeHttpFetcherOverFileFetcherTest>
Alex Deymo2c131bb2016-05-26 16:43:13 -0700428 HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000429TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
430
431namespace {
432class 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}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700476} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000477
478TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700479 HttpFetcherTestDelegate delegate;
480 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
481 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000482
Alex Deymo60ca1a72015-06-18 18:19:15 -0700483 unique_ptr<HttpServer> server(this->test_.CreateServer());
484 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000485
Amin Hassanib2689592019-01-13 17:04:28 -0800486 this->loop_.PostTask(FROM_HERE,
487 base::Bind(StartTransfer,
488 fetcher.get(),
489 this->test_.SmallUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700490 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800491 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000492}
493
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700494TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700495 HttpFetcherTestDelegate delegate;
496 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
497 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700498
Alex Deymo60ca1a72015-06-18 18:19:15 -0700499 unique_ptr<HttpServer> server(this->test_.CreateServer());
500 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700501
Amin Hassanib2689592019-01-13 17:04:28 -0800502 this->loop_.PostTask(
503 FROM_HERE,
504 base::Bind(
505 StartTransfer, fetcher.get(), this->test_.BigUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700506 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800507 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700508}
509
Gilad Arnold48085ba2011-11-16 09:36:08 -0800510// Issue #9648: when server returns an error HTTP response, the fetcher needs to
511// terminate transfer prematurely, rather than try to process the error payload.
512TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800513 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800514 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700515 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800516
Alex Deymo60ca1a72015-06-18 18:19:15 -0700517 // Delegate should expect an error response.
518 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800519
Alex Deymo60ca1a72015-06-18 18:19:15 -0700520 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
521 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800522
Alex Deymo60ca1a72015-06-18 18:19:15 -0700523 unique_ptr<HttpServer> server(this->test_.CreateServer());
524 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800525
Amin Hassanib2689592019-01-13 17:04:28 -0800526 this->loop_.PostTask(FROM_HERE,
527 base::Bind(StartTransfer,
528 fetcher.get(),
529 this->test_.ErrorUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700530 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800531
Alex Deymo60ca1a72015-06-18 18:19:15 -0700532 // Make sure that no bytes were received.
Alex Deymo71f67622017-02-03 21:30:24 -0800533 EXPECT_EQ(0, delegate.times_received_bytes_called_);
534 EXPECT_EQ(0U, fetcher->GetBytesDownloaded());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800535
Alex Deymo60ca1a72015-06-18 18:19:15 -0700536 // Make sure that transfer completion was signaled once, and no termination
537 // was signaled.
Alex Deymo71f67622017-02-03 21:30:24 -0800538 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
539 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800540}
541
Alex Deymofdd6dec2016-03-03 22:35:43 -0800542TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700543 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymofdd6dec2016-03-03 22:35:43 -0800544 return;
545
546 HttpFetcherTestDelegate delegate;
547 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
548 fetcher->set_delegate(&delegate);
549 fetcher->SetHeader("User-Agent", "MyTest");
550 fetcher->SetHeader("user-agent", "Override that header");
551 fetcher->SetHeader("Authorization", "Basic user:passwd");
552
553 // Invalid headers.
554 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
555 fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
556
557 // Hide Accept header normally added by default.
558 fetcher->SetHeader("Accept", "");
559
560 PythonHttpServer server;
561 int port = server.GetPort();
562 ASSERT_TRUE(server.started_);
563
Alex Deymo2c131bb2016-05-26 16:43:13 -0700564 this->loop_.PostTask(
565 FROM_HERE,
566 base::Bind(StartTransfer,
567 fetcher.get(),
568 LocalServerUrlForPath(port, "/echo-headers")));
Alex Deymofdd6dec2016-03-03 22:35:43 -0800569 this->loop_.Run();
570
571 EXPECT_NE(string::npos,
572 delegate.data.find("user-agent: Override that header\r\n"));
573 EXPECT_NE(string::npos,
574 delegate.data.find("Authorization: Basic user:passwd\r\n"));
575
576 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
577 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
578 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
579}
580
rspangler@google.com49fdf182009-10-10 00:57:34 +0000581namespace {
582class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
583 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700584 bool ReceivedBytes(HttpFetcher* fetcher,
585 const void* /* bytes */,
586 size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000587 CHECK(!paused_);
588 paused_ = true;
589 fetcher->Pause();
Amin Hassani0cd9d772018-07-31 23:55:43 -0700590 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000591 }
Alex Deymo610277e2014-11-11 21:18:11 -0800592 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700593 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000594 }
Amin Hassanib2689592019-01-13 17:04:28 -0800595 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000596 void Unpause() {
597 CHECK(paused_);
598 paused_ = false;
599 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000600 }
601 bool paused_;
602 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000603};
604
Alex Deymo60ca1a72015-06-18 18:19:15 -0700605void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
606 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000607 if (delegate->paused_)
608 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700609 // Update the task id with the new scheduled callback.
610 *my_id = MessageLoop::current()->PostDelayedTask(
611 FROM_HERE,
612 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
613 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000614}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700615} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000616
617TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800618 PausingHttpFetcherTestDelegate delegate;
619 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
620 delegate.paused_ = false;
621 delegate.fetcher_ = fetcher.get();
622 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000623
Alex Deymof2858572016-02-25 11:20:13 -0800624 unique_ptr<HttpServer> server(this->test_.CreateServer());
625 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800626
Alex Deymof2858572016-02-25 11:20:13 -0800627 MessageLoop::TaskId callback_id;
628 callback_id = this->loop_.PostDelayedTask(
629 FROM_HERE,
630 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
631 base::TimeDelta::FromMilliseconds(200));
632 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000633
Alex Deymof2858572016-02-25 11:20:13 -0800634 this->loop_.Run();
635 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
636}
637
638// This test will pause the fetcher while the download is not yet started
639// because it is waiting for the proxy to be resolved.
640TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700641 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymof2858572016-02-25 11:20:13 -0800642 return;
643 MockProxyResolver mock_resolver;
644 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
645
646 // Saved arguments from the proxy call.
Alex Deymo35821942017-02-05 04:36:02 +0000647 ProxiesResolvedFn proxy_callback;
648 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _))
649 .WillOnce(DoAll(SaveArg<1>(&proxy_callback), Return(true)));
Alex Deymof2858572016-02-25 11:20:13 -0800650 fetcher->BeginTransfer("http://fake_url");
651 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
652
653 // Pausing and unpausing while resolving the proxy should not affect anything.
654 fetcher->Pause();
655 fetcher->Unpause();
656 fetcher->Pause();
657 // Proxy resolver comes back after we paused the fetcher.
Alex Deymoc00ec562017-02-05 04:36:02 +0000658 ASSERT_FALSE(proxy_callback.is_null());
Alex Deymo35821942017-02-05 04:36:02 +0000659 proxy_callback.Run({1, kNoProxy});
rspangler@google.com49fdf182009-10-10 00:57:34 +0000660}
661
662namespace {
663class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
664 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700665 bool ReceivedBytes(HttpFetcher* fetcher,
666 const void* bytes,
667 size_t length) override {
668 return true;
669 }
Alex Deymo610277e2014-11-11 21:18:11 -0800670 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800671 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700672 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000673 }
Alex Deymo610277e2014-11-11 21:18:11 -0800674 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800675 EXPECT_EQ(fetcher, fetcher_.get());
676 EXPECT_FALSE(once_);
677 EXPECT_TRUE(callback_once_);
678 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700679 // The fetcher could have a callback scheduled on the ProxyResolver that
680 // can fire after this callback. We wait until the end of the test to
681 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800682 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000683 void TerminateTransfer() {
684 CHECK(once_);
685 once_ = false;
686 fetcher_->TerminateTransfer();
687 }
Amin Hassanib2689592019-01-13 17:04:28 -0800688 void EndLoop() { MessageLoop::current()->BreakLoop(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000689 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800690 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700691 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000692};
693
Alex Deymo60ca1a72015-06-18 18:19:15 -0700694void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
695 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000696 if (delegate->once_) {
697 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700698 *my_id = MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800699 FROM_HERE, base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000700 } else {
701 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700702 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000703 }
704}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700705} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000706
707TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700708 AbortingHttpFetcherTestDelegate delegate;
709 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
710 delegate.once_ = true;
711 delegate.callback_once_ = true;
712 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000713
Alex Deymo60ca1a72015-06-18 18:19:15 -0700714 unique_ptr<HttpServer> server(this->test_.CreateServer());
715 this->test_.IgnoreServerAborting(server.get());
716 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800717
Alex Deymo60ca1a72015-06-18 18:19:15 -0700718 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000719
Alex Deymo60ca1a72015-06-18 18:19:15 -0700720 task_id = this->loop_.PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800721 FROM_HERE, base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700722 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
723
724 this->loop_.Run();
725 CHECK(!delegate.once_);
726 CHECK(!delegate.callback_once_);
727 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000728}
729
Alex Deymo71f67622017-02-03 21:30:24 -0800730TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
731 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
732 return;
733 MockProxyResolver mock_resolver;
734 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
735
736 HttpFetcherTestDelegate delegate;
737 fetcher->set_delegate(&delegate);
738
739 EXPECT_CALL(mock_resolver, GetProxiesForUrl(_, _)).WillOnce(Return(123));
740 fetcher->BeginTransfer("http://fake_url");
741 // Run the message loop until idle. This must call the MockProxyResolver with
742 // the request.
743 while (this->loop_.RunOnce(false)) {
744 }
745 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
746
747 EXPECT_CALL(mock_resolver, CancelProxyRequest(123)).WillOnce(Return(true));
748
749 // Terminate the transfer right before the proxy resolution response.
750 fetcher->TerminateTransfer();
751 EXPECT_EQ(0, delegate.times_received_bytes_called_);
752 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
753 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
754}
755
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000756namespace {
757class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
758 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700759 bool ReceivedBytes(HttpFetcher* fetcher,
760 const void* bytes,
761 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800762 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700763 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000764 }
Alex Deymo610277e2014-11-11 21:18:11 -0800765 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700766 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800767 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700768 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000769 }
Amin Hassanib2689592019-01-13 17:04:28 -0800770 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000771 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000772};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700773} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000774
775TYPED_TEST(HttpFetcherTest, FlakyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700776 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000777 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000778 {
779 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700780 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000781 fetcher->set_delegate(&delegate);
782
Ben Chan02f7c1d2014-10-18 15:18:02 -0700783 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800784 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000785
Amin Hassanib2689592019-01-13 17:04:28 -0800786 this->loop_.PostTask(FROM_HERE,
787 base::Bind(&StartTransfer,
788 fetcher.get(),
789 LocalServerUrlForPath(
790 server->GetPort(),
791 base::StringPrintf("/flaky/%d/%d/%d/%d",
792 kBigLength,
793 kFlakyTruncateLength,
794 kFlakySleepEvery,
795 kFlakySleepSecs))));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700796 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000797
798 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800799 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800800 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000801 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
802 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
803 }
804 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000805}
806
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700807namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700808// This delegate kills the server attached to it after receiving any bytes.
809// This can be used for testing what happens when you try to fetch data and
810// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700811class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
812 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700813 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700814 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700815
Alex Deymo610277e2014-11-11 21:18:11 -0800816 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700817 if (server_) {
818 LOG(INFO) << "Stopping server in destructor";
Alex Deymob20de692017-02-05 07:47:37 +0000819 server_.reset();
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700820 LOG(INFO) << "server stopped";
821 }
822 }
823
Amin Hassani0cd9d772018-07-31 23:55:43 -0700824 bool ReceivedBytes(HttpFetcher* fetcher,
825 const void* bytes,
826 size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700827 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700828 LOG(INFO) << "Stopping server in ReceivedBytes";
Alex Deymob20de692017-02-05 07:47:37 +0000829 server_.reset();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700830 LOG(INFO) << "server stopped";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700831 }
Amin Hassani0cd9d772018-07-31 23:55:43 -0700832 return true;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700833 }
Alex Deymo610277e2014-11-11 21:18:11 -0800834 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700835 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700836 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymob20de692017-02-05 07:47:37 +0000837 times_transfer_complete_called_++;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700838 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700839 }
Alex Deymo610277e2014-11-11 21:18:11 -0800840 void TransferTerminated(HttpFetcher* fetcher) override {
Alex Deymob20de692017-02-05 07:47:37 +0000841 times_transfer_terminated_called_++;
842 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800843 }
Alex Deymob20de692017-02-05 07:47:37 +0000844 unique_ptr<PythonHttpServer> server_;
845 int times_transfer_terminated_called_{0};
846 int times_transfer_complete_called_{0};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700847};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700848} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700849
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700850TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700851 // This test ensures that a fetcher responds correctly when a server isn't
852 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800853 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700854 return;
Alex Deymob20de692017-02-05 07:47:37 +0000855 FailureHttpFetcherTestDelegate delegate(nullptr);
856 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
857 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700858
Alex Deymob20de692017-02-05 07:47:37 +0000859 this->loop_.PostTask(
860 FROM_HERE,
861 base::Bind(
862 StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
863 this->loop_.Run();
864 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
865 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700866
Alex Deymob20de692017-02-05 07:47:37 +0000867 // Exiting and testing happens in the delegate
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700868}
869
Alex Deymof123ae22015-09-24 14:59:43 -0700870TYPED_TEST(HttpFetcherTest, NoResponseTest) {
871 // This test starts a new http server but the server doesn't respond and just
872 // closes the connection.
873 if (this->test_.IsMock())
874 return;
875
876 PythonHttpServer* server = new PythonHttpServer();
877 int port = server->GetPort();
878 ASSERT_TRUE(server->started_);
879
880 // Handles destruction and claims ownership.
881 FailureHttpFetcherTestDelegate delegate(server);
882 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
883 fetcher->set_delegate(&delegate);
884 // The server will not reply at all, so we can limit the execution time of the
885 // test by reducing the low-speed timeout to something small. The test will
886 // finish once the TimeoutCallback() triggers (every second) and the timeout
887 // expired.
888 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
889
Amin Hassanib2689592019-01-13 17:04:28 -0800890 this->loop_.PostTask(
891 FROM_HERE,
892 base::Bind(
893 StartTransfer, fetcher.get(), LocalServerUrlForPath(port, "/hang")));
Alex Deymof123ae22015-09-24 14:59:43 -0700894 this->loop_.Run();
Alex Deymob20de692017-02-05 07:47:37 +0000895 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
896 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Alex Deymof123ae22015-09-24 14:59:43 -0700897
898 // Check that no other callback runs in the next two seconds. That would
899 // indicate a leaked callback.
900 bool timeout = false;
Luis Hector Chavezf1cf3482016-07-19 14:29:19 -0700901 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
902 base::Unretained(&timeout));
Amin Hassanib2689592019-01-13 17:04:28 -0800903 this->loop_.PostDelayedTask(
904 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
Alex Deymof123ae22015-09-24 14:59:43 -0700905 EXPECT_TRUE(this->loop_.RunOnce(true));
906 EXPECT_TRUE(timeout);
907}
908
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700909TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700910 // This test starts a new http server and kills it after receiving its first
911 // set of bytes. It test whether or not our fetcher eventually gives up on
912 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800913 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700914 return;
Alex Deymob20de692017-02-05 07:47:37 +0000915 PythonHttpServer* server = new PythonHttpServer();
916 int port = server->GetPort();
917 ASSERT_TRUE(server->started_);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700918
Alex Deymob20de692017-02-05 07:47:37 +0000919 // Handles destruction and claims ownership.
920 FailureHttpFetcherTestDelegate delegate(server);
921 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
922 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700923
Alex Deymob20de692017-02-05 07:47:37 +0000924 this->loop_.PostTask(
925 FROM_HERE,
926 base::Bind(StartTransfer,
927 fetcher.get(),
928 LocalServerUrlForPath(port,
929 base::StringPrintf("/flaky/%d/%d/%d/%d",
930 kBigLength,
931 kFlakyTruncateLength,
932 kFlakySleepEvery,
933 kFlakySleepSecs))));
934 this->loop_.Run();
935 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
936 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700937
Alex Deymob20de692017-02-05 07:47:37 +0000938 // Exiting and testing happens in the delegate
939}
940
941// Test that we can cancel a transfer while it is still trying to connect to the
942// server. This test kills the server after a few bytes are received.
943TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
944 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
945 return;
946
947 PythonHttpServer* server = new PythonHttpServer();
948 int port = server->GetPort();
949 ASSERT_TRUE(server->started_);
950
951 // Handles destruction and claims ownership.
952 FailureHttpFetcherTestDelegate delegate(server);
953 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
954 fetcher->set_delegate(&delegate);
955
956 this->loop_.PostTask(
957 FROM_HERE,
958 base::Bind(StartTransfer,
959 fetcher.get(),
960 LocalServerUrlForPath(port,
961 base::StringPrintf("/flaky/%d/%d/%d/%d",
962 kBigLength,
963 kFlakyTruncateLength,
964 kFlakySleepEvery,
965 kFlakySleepSecs))));
966 // Terminating the transfer after 3 seconds gives it a chance to contact the
967 // server and enter the retry loop.
968 this->loop_.PostDelayedTask(FROM_HERE,
969 base::Bind(&HttpFetcher::TerminateTransfer,
970 base::Unretained(fetcher.get())),
971 base::TimeDelta::FromSeconds(3));
972
973 // Exiting and testing happens in the delegate.
974 this->loop_.Run();
975 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
976 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
977
978 // Check that no other callback runs in the next two seconds. That would
979 // indicate a leaked callback.
980 bool timeout = false;
981 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
982 base::Unretained(&timeout));
983 this->loop_.PostDelayedTask(
984 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
985 EXPECT_TRUE(this->loop_.RunOnce(true));
986 EXPECT_TRUE(timeout);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700987}
988
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700989namespace {
Amin Hassanib2689592019-01-13 17:04:28 -0800990const HttpResponseCode kRedirectCodes[] = {kHttpResponseMovedPermanently,
991 kHttpResponseFound,
992 kHttpResponseSeeOther,
993 kHttpResponseTempRedirect};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700994
995class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
996 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700997 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700998 : expected_successful_(expected_successful) {}
Amin Hassani0cd9d772018-07-31 23:55:43 -0700999 bool ReceivedBytes(HttpFetcher* fetcher,
1000 const void* bytes,
1001 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001002 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001003 return true;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001004 }
Alex Deymo610277e2014-11-11 21:18:11 -08001005 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001006 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001007 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001008 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001009 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001010 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
1011 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -07001012 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001013 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001014 }
Amin Hassanib2689592019-01-13 17:04:28 -08001015 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001016 bool expected_successful_;
1017 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001018};
1019
1020// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001021void RedirectTest(const HttpServer* server,
1022 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001023 const string& url,
1024 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001025 RedirectHttpFetcherTestDelegate delegate(expected_successful);
1026 unique_ptr<HttpFetcher> fetcher(http_fetcher);
1027 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001028
Amin Hassanib2689592019-01-13 17:04:28 -08001029 MessageLoop::current()->PostTask(
1030 FROM_HERE,
1031 base::Bind(StartTransfer,
1032 fetcher.get(),
1033 LocalServerUrlForPath(server->GetPort(), url)));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001034 MessageLoop::current()->Run();
1035 if (expected_successful) {
1036 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -08001037 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -07001038 for (int i = 0; i < kMediumLength; i += 10) {
1039 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
1040 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001041 }
1042 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001043}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001044} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001045
1046TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001047 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001048 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001049
Ben Chan02f7c1d2014-10-18 15:18:02 -07001050 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001051 ASSERT_TRUE(server->started_);
1052
hscham00b6aa22020-02-20 12:32:06 +09001053 for (size_t c = 0; c < base::size(kRedirectCodes); ++c) {
Amin Hassanib2689592019-01-13 17:04:28 -08001054 const string url = base::StringPrintf(
1055 "/redirect/%d/download/%d", kRedirectCodes[c], kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001056 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001057 }
1058}
1059
1060TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
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; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001069 url += base::StringPrintf("/redirect/%d",
hscham00b6aa22020-02-20 12:32:06 +09001070 kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001071 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001072 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001073 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001074}
1075
1076TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001077 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001078 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001079
Ben Chan02f7c1d2014-10-18 15:18:02 -07001080 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001081 ASSERT_TRUE(server->started_);
1082
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001083 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001084 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001085 url += base::StringPrintf("/redirect/%d",
hscham00b6aa22020-02-20 12:32:06 +09001086 kRedirectCodes[r % base::size(kRedirectCodes)]);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001087 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001088 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001089 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001090}
1091
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001092namespace {
1093class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1094 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001095 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001096 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001097
Amin Hassani0cd9d772018-07-31 23:55:43 -07001098 bool ReceivedBytes(HttpFetcher* fetcher,
1099 const void* bytes,
1100 size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001101 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001102 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001103 return true;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001104 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001105
Alex Deymo610277e2014-11-11 21:18:11 -08001106 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001107 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001108 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001109 if (expected_response_code_ != 0)
1110 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001111 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -07001112 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001113 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001114 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001115
Amin Hassanib2689592019-01-13 17:04:28 -08001116 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001117
Ben Chan02f7c1d2014-10-18 15:18:02 -07001118 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001119 int expected_response_code_;
1120 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001121};
1122
1123void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -03001124 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001125 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -07001126 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001127 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -08001128 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001129 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001130 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1131 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001132
Alex Deymo60ca1a72015-06-18 18:19:15 -07001133 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -08001134 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001135 ASSERT_TRUE(multi_fetcher);
1136 multi_fetcher->ClearRanges();
1137 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
Amin Hassanib2689592019-01-13 17:04:28 -08001138 e = ranges.end();
1139 it != e;
1140 ++it) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001141 string tmp_str = base::StringPrintf("%jd+", it->first);
1142 if (it->second > 0) {
1143 base::StringAppendF(&tmp_str, "%jd", it->second);
1144 multi_fetcher->AddRange(it->first, it->second);
1145 } else {
1146 base::StringAppendF(&tmp_str, "?");
1147 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001148 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001149 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001150 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001151 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001152 multi_fetcher->set_delegate(&delegate);
1153
1154 MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -08001155 FROM_HERE, base::Bind(StartTransfer, multi_fetcher, url));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001156 MessageLoop::current()->Run();
1157
1158 EXPECT_EQ(expected_size, delegate.data.size());
1159 EXPECT_EQ(expected_prefix,
1160 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001161}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001162} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001163
Darin Petkov9ce452b2010-11-17 14:33:28 -08001164TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001165 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001166 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001167
Ben Chan02f7c1d2014-10-18 15:18:02 -07001168 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001169 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001170
Ben Chanf9cb98c2014-09-21 18:31:30 -07001171 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001172 ranges.push_back(make_pair(0, 25));
Tao Bao642b32b2019-01-02 15:33:42 -08001173 ranges.push_back(make_pair(99, 17));
1174 MultiTest(this->test_.NewLargeFetcher(),
1175 this->test_.fake_hardware(),
1176 this->test_.BigUrl(server->GetPort()),
1177 ranges,
1178 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1179 25 + 17,
1180 this->test_.IsFileFetcher() ? kHttpResponseOk
1181 : kHttpResponsePartialContent);
1182}
1183
1184TYPED_TEST(HttpFetcherTest, MultiHttpFetcherUnspecifiedEndTest) {
1185 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1186 return;
1187
1188 unique_ptr<HttpServer> server(this->test_.CreateServer());
1189 ASSERT_TRUE(server->started_);
1190
1191 vector<pair<off_t, off_t>> ranges;
1192 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001193 ranges.push_back(make_pair(99, 0));
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 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001199 kBigLength - (99 - 25),
1200 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001201}
1202
1203TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001204 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001205 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001206
Ben Chan02f7c1d2014-10-18 15:18:02 -07001207 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001208 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001209
Ben Chanf9cb98c2014-09-21 18:31:30 -07001210 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001211 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001212 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001213 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001214 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001215 ranges,
1216 "abcdefghijabcdefghijabcd",
1217 24,
Tao Bao642b32b2019-01-02 15:33:42 -08001218 this->test_.IsFileFetcher() ? kHttpResponseOk
1219 : kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001220}
1221
1222TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001223 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001224 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001225
Ben Chan02f7c1d2014-10-18 15:18:02 -07001226 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001227 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001228
Ben Chanf9cb98c2014-09-21 18:31:30 -07001229 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001230 ranges.push_back(make_pair(kBigLength - 2, 0));
1231 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001232 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001233 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001234 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001235 ranges,
1236 "ijhij",
1237 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001238 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001239}
1240
1241TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001242 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001243 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001244
Ben Chan02f7c1d2014-10-18 15:18:02 -07001245 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001246 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001247
Ben Chanf9cb98c2014-09-21 18:31:30 -07001248 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001249 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001250 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001251 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001252 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001253 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001254 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001255 ranges,
1256 "ij",
1257 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001258 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001259 ranges.push_back(make_pair(0, 5));
1260 }
1261}
1262
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001263// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1264// should retry with other proxies listed before giving up.
1265//
1266// (1) successful recovery: The offset fetch will fail twice but succeed with
1267// the third proxy.
1268TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001269 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001270 return;
1271
Ben Chan02f7c1d2014-10-18 15:18:02 -07001272 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001273 ASSERT_TRUE(server->started_);
1274
Ben Chanf9cb98c2014-09-21 18:31:30 -07001275 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001276 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001277 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001278 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001279 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001280 LocalServerUrlForPath(
1281 server->GetPort(),
1282 base::StringPrintf("/error-if-offset/%d/2", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001283 ranges,
1284 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1285 kBigLength - (99 - 25),
1286 kHttpResponsePartialContent);
1287}
1288
1289// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1290// fetcher will signal a (failed) completed transfer to the delegate.
1291TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001292 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001293 return;
1294
Ben Chan02f7c1d2014-10-18 15:18:02 -07001295 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001296 ASSERT_TRUE(server->started_);
1297
Ben Chanf9cb98c2014-09-21 18:31:30 -07001298 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001299 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001300 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001301 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001302 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001303 LocalServerUrlForPath(
1304 server->GetPort(),
1305 base::StringPrintf("/error-if-offset/%d/3", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001306 ranges,
1307 "abcdefghijabcdefghijabcde", // only received the first chunk
1308 25,
1309 kHttpResponseUndefined);
1310}
1311
Alex Deymo4ea2d922017-02-05 07:35:32 +00001312namespace {
1313// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1314class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1315 public:
1316 explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1317 : terminate_trigger_bytes_(terminate_trigger_bytes) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001318
Amin Hassani0cd9d772018-07-31 23:55:43 -07001319 bool ReceivedBytes(HttpFetcher* fetcher,
Alex Deymo4ea2d922017-02-05 07:35:32 +00001320 const void* bytes,
1321 size_t length) override {
1322 LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
1323 EXPECT_EQ(fetcher, fetcher_.get());
Tao Bao642b32b2019-01-02 15:33:42 -08001324 bool should_terminate = false;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001325 if (bytes_downloaded_ < terminate_trigger_bytes_ &&
1326 bytes_downloaded_ + length >= terminate_trigger_bytes_) {
1327 MessageLoop::current()->PostTask(
1328 FROM_HERE,
1329 base::Bind(&HttpFetcher::TerminateTransfer,
1330 base::Unretained(fetcher_.get())));
Tao Bao642b32b2019-01-02 15:33:42 -08001331 should_terminate = true;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001332 }
1333 bytes_downloaded_ += length;
Tao Bao642b32b2019-01-02 15:33:42 -08001334 return !should_terminate;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001335 }
1336
1337 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1338 ADD_FAILURE() << "TransferComplete called but expected a failure";
1339 // Destroy the fetcher (because we're allowed to).
1340 fetcher_.reset(nullptr);
1341 MessageLoop::current()->BreakLoop();
1342 }
1343
1344 void TransferTerminated(HttpFetcher* fetcher) override {
1345 // Destroy the fetcher (because we're allowed to).
1346 fetcher_.reset(nullptr);
1347 MessageLoop::current()->BreakLoop();
1348 }
1349
1350 unique_ptr<HttpFetcher> fetcher_;
1351 size_t bytes_downloaded_{0};
1352 size_t terminate_trigger_bytes_;
1353};
1354} // namespace
1355
1356TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
1357 if (!this->test_.IsMulti())
1358 return;
1359 const size_t kRangeTrigger = 1000;
1360 MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
1361
1362 unique_ptr<HttpServer> server(this->test_.CreateServer());
1363 ASSERT_TRUE(server->started_);
1364
1365 MultiRangeHttpFetcher* multi_fetcher =
1366 static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
1367 ASSERT_TRUE(multi_fetcher);
1368 // Transfer ownership of the fetcher to the delegate.
1369 delegate.fetcher_.reset(multi_fetcher);
1370 multi_fetcher->set_delegate(&delegate);
1371
1372 multi_fetcher->ClearRanges();
1373 multi_fetcher->AddRange(45, kRangeTrigger);
1374 multi_fetcher->AddRange(2000, 100);
1375
1376 this->test_.fake_hardware()->SetIsOfficialBuild(false);
1377
1378 StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
1379 MessageLoop::current()->Run();
1380
1381 // Check that the delegate made it to the trigger point.
1382 EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
1383}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001384
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001385namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001386class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001387 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -07001388 bool ReceivedBytes(HttpFetcher* fetcher,
1389 const void* bytes,
1390 size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001391 ADD_FAILURE();
Amin Hassani0cd9d772018-07-31 23:55:43 -07001392 return true;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001393 }
Alex Deymo610277e2014-11-11 21:18:11 -08001394 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001395 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001396 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001397 }
Amin Hassanib2689592019-01-13 17:04:28 -08001398 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001399};
1400
Alex Deymo60ca1a72015-06-18 18:19:15 -07001401void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1402 bool is_official_build) {
1403 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1404 return;
1405
1406 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1407 ASSERT_TRUE(server->started_);
1408
1409 BlockedTransferTestDelegate delegate;
1410 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1411 LOG(INFO) << "is_official_build: " << is_official_build;
1412 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001413 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001414 fetcher->set_delegate(&delegate);
1415
Amin Hassanib2689592019-01-13 17:04:28 -08001416 MessageLoop::current()->PostTask(
1417 FROM_HERE,
1418 base::Bind(
1419 StartTransfer,
1420 fetcher.get(),
1421 LocalServerUrlForPath(server->GetPort(),
1422 fetcher_test->SmallUrl(server->GetPort()))));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001423 MessageLoop::current()->Run();
1424}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001425} // namespace
1426
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001427TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001428 BlockedTransferTestHelper(&this->test_, false);
1429}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001430
Alex Deymo60ca1a72015-06-18 18:19:15 -07001431TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1432 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001433}
1434
rspangler@google.com49fdf182009-10-10 00:57:34 +00001435} // namespace chromeos_update_engine