blob: 237ea209c6dde1859c497c02338c1107354ad16e [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>
32#include <base/strings/string_number_conversions.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070033#include <base/strings/string_util.h>
34#include <base/strings/stringprintf.h>
35#include <base/time/time.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070036#include <brillo/message_loops/base_message_loop.h>
37#include <brillo/message_loops/message_loop.h>
38#include <brillo/message_loops/message_loop_utils.h>
39#include <brillo/process.h>
40#include <brillo/streams/file_stream.h>
41#include <brillo/streams/stream.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080042#include <gtest/gtest.h>
43
Alex Deymoc1c17b42015-11-23 03:53:15 -030044#include "update_engine/common/fake_hardware.h"
Alex Deymo2c131bb2016-05-26 16:43:13 -070045#include "update_engine/common/file_fetcher.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080046#include "update_engine/common/http_common.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080047#include "update_engine/common/mock_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070048#include "update_engine/common/mock_proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080049#include "update_engine/common/multi_range_http_fetcher.h"
Sen Jiangd8be4b52018-09-18 16:06:57 -070050#include "update_engine/common/proxy_resolver.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080051#include "update_engine/common/test_utils.h"
52#include "update_engine/common/utils.h"
Alex Deymo14c0da82016-07-20 16:45:45 -070053#include "update_engine/libcurl_http_fetcher.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000054
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070055using brillo::MessageLoop;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070056using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080057using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000058using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070059using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000060using std::vector;
Amin Hassanib2689592019-01-13 17:04:28 -080061using testing::_;
Alex Deymof2858572016-02-25 11:20:13 -080062using testing::DoAll;
63using testing::Return;
64using testing::SaveArg;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000065
Gilad Arnold9bedeb52011-11-17 16:19:57 -080066namespace {
67
Amin Hassanib2689592019-01-13 17:04:28 -080068const int kBigLength = 100000;
69const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080070const int kFlakyTruncateLength = 29000;
Amin Hassanib2689592019-01-13 17:04:28 -080071const int kFlakySleepEvery = 3;
72const int kFlakySleepSecs = 10;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080073
74} // namespace
75
rspangler@google.com49fdf182009-10-10 00:57:34 +000076namespace chromeos_update_engine {
77
Amin Hassanib2689592019-01-13 17:04:28 -080078static const char* kUnusedUrl = "unused://unused";
Gilad Arnold9bedeb52011-11-17 16:19:57 -080079
Amin Hassanib2689592019-01-13 17:04:28 -080080static inline string LocalServerUrlForPath(in_port_t port, const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070081 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Amin Hassanib2689592019-01-13 17:04:28 -080082 return base::StringPrintf(
83 "http://127.0.0.1%s%s", port_str.c_str(), path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000084}
85
Gilad Arnold9bedeb52011-11-17 16:19:57 -080086//
87// Class hierarchy for HTTP server implementations.
88//
89
90class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000091 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080092 // This makes it an abstract class (dirty but works).
93 virtual ~HttpServer() = 0;
94
Amin Hassanib2689592019-01-13 17:04:28 -080095 virtual in_port_t GetPort() const { return 0; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070096
rspangler@google.com49fdf182009-10-10 00:57:34 +000097 bool started_;
98};
99
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800100HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000101
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800102class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000103 public:
Amin Hassanib2689592019-01-13 17:04:28 -0800104 NullHttpServer() { started_ = true; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000105};
106
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800107class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000108 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700109 PythonHttpServer() : port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000110 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700111
112 // Spawn the server process.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700113 unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
Sen Jiang260f03b2016-03-21 15:34:58 -0700114 http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
Alex Deymo535f3b72015-08-07 10:51:32 -0700115 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
116
117 if (!http_server->Start()) {
118 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000119 return;
120 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700121 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700122
123 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700124 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700125 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
126 if (!stdout)
127 return;
128
129 vector<char> buf(128);
130 string line;
131 while (line.find('\n') == string::npos) {
132 size_t read;
133 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
134 ADD_FAILURE() << "error reading http server stdout";
135 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700136 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700137 line.append(buf.data(), read);
138 if (read == 0)
139 break;
140 }
141 // Parse the port from the output line.
142 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
143 if (line.size() < listening_msg_prefix_len) {
144 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700145 return;
146 }
147
Alex Deymo535f3b72015-08-07 10:51:32 -0700148 EXPECT_EQ(kServerListeningMsgPrefix,
149 line.substr(0, listening_msg_prefix_len));
150 string port_str = line.substr(listening_msg_prefix_len);
151 port_str.resize(port_str.find('\n'));
152 EXPECT_TRUE(base::StringToUint(port_str, &port_));
153
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700154 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700155 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700156
157 // Any failure before this point will SIGKILL the test server if started
158 // when the |http_server| goes out of scope.
159 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000160 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800161
rspangler@google.com49fdf182009-10-10 00:57:34 +0000162 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700163 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700164 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000165 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700166 // Wait up to 10 seconds for the process to finish. Destroying the process
167 // will kill it with a SIGKILL otherwise.
168 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000169 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800170
Amin Hassanib2689592019-01-13 17:04:28 -0800171 in_port_t GetPort() const override { return port_; }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700172
173 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700174 static const char* kServerListeningMsgPrefix;
175
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700176 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700177 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000178};
179
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700180const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
181
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800182//
183// Class hierarchy for HTTP fetcher test wrappers.
184//
185
186class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000187 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700188 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700189 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700190
Alex Deymof2858572016-02-25 11:20:13 -0800191 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
192 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
193 proxy_resolver_.set_num_proxies(num_proxies);
194 return NewLargeFetcher(&proxy_resolver_);
195 }
Amin Hassanib2689592019-01-13 17:04:28 -0800196 HttpFetcher* NewLargeFetcher() { return NewLargeFetcher(1); }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800197
Alex Deymof2858572016-02-25 11:20:13 -0800198 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800199 HttpFetcher* NewSmallFetcher() {
Alex Deymof2858572016-02-25 11:20:13 -0800200 proxy_resolver_.set_num_proxies(1);
201 return NewSmallFetcher(&proxy_resolver_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800202 }
203
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700204 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
205 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
206 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800207
208 virtual bool IsMock() const = 0;
209 virtual bool IsMulti() const = 0;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700210 virtual bool IsHttpSupported() const = 0;
Tao Bao642b32b2019-01-02 15:33:42 -0800211 virtual bool IsFileFetcher() const = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800212
213 virtual void IgnoreServerAborting(HttpServer* server) const {}
214
Alex Deymo60ca1a72015-06-18 18:19:15 -0700215 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800216
Amin Hassanib2689592019-01-13 17:04:28 -0800217 FakeHardware* fake_hardware() { return &fake_hardware_; }
Alex Deymoc1c17b42015-11-23 03:53:15 -0300218
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800219 protected:
220 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300221 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800222};
223
224class MockHttpFetcherTest : public AnyHttpFetcherTest {
225 public:
226 // Necessary to unhide the definition in the base class.
227 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800228 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700229 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800230 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800231 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800232 }
233
234 // Necessary to unhide the definition in the base class.
235 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800236 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
237 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800238 }
239
Alex Deymo610277e2014-11-11 21:18:11 -0800240 bool IsMock() const override { return true; }
241 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700242 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800243 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800244
Amin Hassanib2689592019-01-13 17:04:28 -0800245 HttpServer* CreateServer() override { return new NullHttpServer; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800246};
247
248class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
249 public:
250 // Necessary to unhide the definition in the base class.
251 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800252 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
253 LibcurlHttpFetcher* ret =
254 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700255 // Speed up test execution.
256 ret->set_idle_seconds(1);
257 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300258 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000259 return ret;
260 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800261
262 // Necessary to unhide the definition in the base class.
263 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800264 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
265 return NewLargeFetcher(proxy_resolver);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000266 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800267
Alex Deymo610277e2014-11-11 21:18:11 -0800268 string BigUrl(in_port_t port) const override {
Amin Hassanib2689592019-01-13 17:04:28 -0800269 return LocalServerUrlForPath(
270 port, base::StringPrintf("/download/%d", kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000271 }
Alex Deymo610277e2014-11-11 21:18:11 -0800272 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700273 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000274 }
Alex Deymo610277e2014-11-11 21:18:11 -0800275 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700276 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800277 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800278
Alex Deymo610277e2014-11-11 21:18:11 -0800279 bool IsMock() const override { return false; }
280 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700281 bool IsHttpSupported() const override { return true; }
Tao Bao642b32b2019-01-02 15:33:42 -0800282 bool IsFileFetcher() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800283
Alex Deymo610277e2014-11-11 21:18:11 -0800284 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700285 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700286 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800287
Amin Hassanib2689592019-01-13 17:04:28 -0800288 HttpServer* CreateServer() override { return new PythonHttpServer; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000289};
290
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800291class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700292 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800293 // Necessary to unhide the definition in the base class.
294 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800295 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
296 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
297 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800298 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800299 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700300 // Speed up test execution.
301 ret->set_idle_seconds(1);
302 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300303 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700304 return ret;
305 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800306
307 // Necessary to unhide the definition in the base class.
308 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800309 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
310 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800311 }
312
Alex Deymo610277e2014-11-11 21:18:11 -0800313 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700314};
315
Alex Deymo2c131bb2016-05-26 16:43:13 -0700316class FileFetcherTest : public AnyHttpFetcherTest {
317 public:
318 // Necessary to unhide the definition in the base class.
319 using AnyHttpFetcherTest::NewLargeFetcher;
320 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
321 return new FileFetcher();
322 }
323
324 // Necessary to unhide the definition in the base class.
325 using AnyHttpFetcherTest::NewSmallFetcher;
326 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
327 return NewLargeFetcher(proxy_resolver);
328 }
329
330 string BigUrl(in_port_t port) const override {
Tao Bao642b32b2019-01-02 15:33:42 -0800331 static string big_contents = []() {
332 string buf;
333 buf.reserve(kBigLength);
334 constexpr const char* kBigUrlContent = "abcdefghij";
335 for (size_t i = 0; i < kBigLength; i += strlen(kBigUrlContent)) {
336 buf.append(kBigUrlContent,
337 std::min(kBigLength - i, strlen(kBigUrlContent)));
338 }
339 return buf;
340 }();
341 test_utils::WriteFileString(temp_file_.path(), big_contents);
Alex Deymo2c131bb2016-05-26 16:43:13 -0700342 return "file://" + temp_file_.path();
343 }
344 string SmallUrl(in_port_t port) const override {
345 test_utils::WriteFileString(temp_file_.path(), "small contents");
346 return "file://" + temp_file_.path();
347 }
348 string ErrorUrl(in_port_t port) const override {
349 return "file:///path/to/non-existing-file";
350 }
351
352 bool IsMock() const override { return false; }
353 bool IsMulti() const override { return false; }
354 bool IsHttpSupported() const override { return false; }
Tao Bao642b32b2019-01-02 15:33:42 -0800355 bool IsFileFetcher() const override { return true; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700356
357 void IgnoreServerAborting(HttpServer* server) const override {}
358
359 HttpServer* CreateServer() override { return new NullHttpServer; }
360
361 private:
362 test_utils::ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
363};
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800364
Tao Bao642b32b2019-01-02 15:33:42 -0800365class MultiRangeHttpFetcherOverFileFetcherTest : public FileFetcherTest {
366 public:
367 // Necessary to unhide the definition in the base class.
368 using AnyHttpFetcherTest::NewLargeFetcher;
369 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
370 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(new FileFetcher());
371 ret->ClearRanges();
372 // FileFetcher doesn't support range with unspecified length.
373 ret->AddRange(0, 1);
374 // Speed up test execution.
375 ret->set_idle_seconds(1);
376 ret->set_retry_seconds(1);
377 fake_hardware_.SetIsOfficialBuild(false);
378 return ret;
379 }
380
381 // Necessary to unhide the definition in the base class.
382 using AnyHttpFetcherTest::NewSmallFetcher;
383 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
384 return NewLargeFetcher(proxy_resolver);
385 }
386
387 bool IsMulti() const override { return true; }
388};
389
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800390//
391// Infrastructure for type tests of HTTP fetcher.
392// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
393//
394
395// Fixture class template. We use an explicit constraint to guarantee that it
396// can only be instantiated with an AnyHttpFetcherTest type, see:
397// http://www2.research.att.com/~bs/bs_faq2.html#constraints
398template <typename T>
399class HttpFetcherTest : public ::testing::Test {
400 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700401 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700402 brillo::BaseMessageLoop loop_{&base_loop_};
Alex Deymo60ca1a72015-06-18 18:19:15 -0700403
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800404 T test_;
405
Alex Deymo60ca1a72015-06-18 18:19:15 -0700406 protected:
Amin Hassanib2689592019-01-13 17:04:28 -0800407 HttpFetcherTest() { loop_.SetAsCurrent(); }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700408
409 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700410 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700411 }
412
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800413 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700414 static void TypeConstraint(T* a) {
Amin Hassanib2689592019-01-13 17:04:28 -0800415 AnyHttpFetcherTest* b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700416 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700417 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800418 }
419};
420
421// Test case types list.
422typedef ::testing::Types<LibcurlHttpFetcherTest,
423 MockHttpFetcherTest,
Alex Deymo2c131bb2016-05-26 16:43:13 -0700424 MultiRangeHttpFetcherTest,
Tao Bao642b32b2019-01-02 15:33:42 -0800425 FileFetcherTest,
426 MultiRangeHttpFetcherOverFileFetcherTest>
Alex Deymo2c131bb2016-05-26 16:43:13 -0700427 HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000428TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
429
430namespace {
431class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000432 public:
Alex Deymofdd6dec2016-03-03 22:35:43 -0800433 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800434
Amin Hassani0cd9d772018-07-31 23:55:43 -0700435 bool ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymofdd6dec2016-03-03 22:35:43 -0800436 const void* bytes,
437 size_t length) override {
438 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800439 // Update counters
440 times_received_bytes_called_++;
Amin Hassani0cd9d772018-07-31 23:55:43 -0700441 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000442 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800443
Alex Deymo610277e2014-11-11 21:18:11 -0800444 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800445 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800446 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800447 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800448 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700449 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800450
451 // Update counter
452 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000453 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800454
Alex Deymo610277e2014-11-11 21:18:11 -0800455 void TransferTerminated(HttpFetcher* fetcher) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800456 times_transfer_terminated_called_++;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700457 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800458 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800459
Gilad Arnold48085ba2011-11-16 09:36:08 -0800460 // Are we expecting an error response? (default: no)
Alex Deymofdd6dec2016-03-03 22:35:43 -0800461 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800462
463 // Counters for callback invocations.
Alex Deymofdd6dec2016-03-03 22:35:43 -0800464 int times_transfer_complete_called_{0};
465 int times_transfer_terminated_called_{0};
466 int times_received_bytes_called_{0};
467
468 // The received data bytes.
469 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000470};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000471
Alex Deymo60ca1a72015-06-18 18:19:15 -0700472void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
473 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000474}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700475} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000476
477TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700478 HttpFetcherTestDelegate delegate;
479 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
480 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000481
Alex Deymo60ca1a72015-06-18 18:19:15 -0700482 unique_ptr<HttpServer> server(this->test_.CreateServer());
483 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000484
Amin Hassanib2689592019-01-13 17:04:28 -0800485 this->loop_.PostTask(FROM_HERE,
486 base::Bind(StartTransfer,
487 fetcher.get(),
488 this->test_.SmallUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700489 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800490 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000491}
492
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700493TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700494 HttpFetcherTestDelegate delegate;
495 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
496 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700497
Alex Deymo60ca1a72015-06-18 18:19:15 -0700498 unique_ptr<HttpServer> server(this->test_.CreateServer());
499 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700500
Amin Hassanib2689592019-01-13 17:04:28 -0800501 this->loop_.PostTask(
502 FROM_HERE,
503 base::Bind(
504 StartTransfer, fetcher.get(), this->test_.BigUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700505 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800506 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700507}
508
Gilad Arnold48085ba2011-11-16 09:36:08 -0800509// Issue #9648: when server returns an error HTTP response, the fetcher needs to
510// terminate transfer prematurely, rather than try to process the error payload.
511TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800512 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800513 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700514 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800515
Alex Deymo60ca1a72015-06-18 18:19:15 -0700516 // Delegate should expect an error response.
517 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800518
Alex Deymo60ca1a72015-06-18 18:19:15 -0700519 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
520 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800521
Alex Deymo60ca1a72015-06-18 18:19:15 -0700522 unique_ptr<HttpServer> server(this->test_.CreateServer());
523 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800524
Amin Hassanib2689592019-01-13 17:04:28 -0800525 this->loop_.PostTask(FROM_HERE,
526 base::Bind(StartTransfer,
527 fetcher.get(),
528 this->test_.ErrorUrl(server->GetPort())));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700529 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800530
Alex Deymo60ca1a72015-06-18 18:19:15 -0700531 // Make sure that no bytes were received.
Alex Deymo71f67622017-02-03 21:30:24 -0800532 EXPECT_EQ(0, delegate.times_received_bytes_called_);
533 EXPECT_EQ(0U, fetcher->GetBytesDownloaded());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800534
Alex Deymo60ca1a72015-06-18 18:19:15 -0700535 // Make sure that transfer completion was signaled once, and no termination
536 // was signaled.
Alex Deymo71f67622017-02-03 21:30:24 -0800537 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
538 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800539}
540
Alex Deymofdd6dec2016-03-03 22:35:43 -0800541TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700542 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymofdd6dec2016-03-03 22:35:43 -0800543 return;
544
545 HttpFetcherTestDelegate delegate;
546 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
547 fetcher->set_delegate(&delegate);
548 fetcher->SetHeader("User-Agent", "MyTest");
549 fetcher->SetHeader("user-agent", "Override that header");
550 fetcher->SetHeader("Authorization", "Basic user:passwd");
551
552 // Invalid headers.
553 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
554 fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
555
556 // Hide Accept header normally added by default.
557 fetcher->SetHeader("Accept", "");
558
559 PythonHttpServer server;
560 int port = server.GetPort();
561 ASSERT_TRUE(server.started_);
562
Alex Deymo2c131bb2016-05-26 16:43:13 -0700563 this->loop_.PostTask(
564 FROM_HERE,
565 base::Bind(StartTransfer,
566 fetcher.get(),
567 LocalServerUrlForPath(port, "/echo-headers")));
Alex Deymofdd6dec2016-03-03 22:35:43 -0800568 this->loop_.Run();
569
570 EXPECT_NE(string::npos,
571 delegate.data.find("user-agent: Override that header\r\n"));
572 EXPECT_NE(string::npos,
573 delegate.data.find("Authorization: Basic user:passwd\r\n"));
574
575 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
576 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
577 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
578}
579
rspangler@google.com49fdf182009-10-10 00:57:34 +0000580namespace {
581class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
582 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700583 bool ReceivedBytes(HttpFetcher* fetcher,
584 const void* /* bytes */,
585 size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000586 CHECK(!paused_);
587 paused_ = true;
588 fetcher->Pause();
Amin Hassani0cd9d772018-07-31 23:55:43 -0700589 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000590 }
Alex Deymo610277e2014-11-11 21:18:11 -0800591 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700592 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000593 }
Amin Hassanib2689592019-01-13 17:04:28 -0800594 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000595 void Unpause() {
596 CHECK(paused_);
597 paused_ = false;
598 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000599 }
600 bool paused_;
601 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000602};
603
Alex Deymo60ca1a72015-06-18 18:19:15 -0700604void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
605 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000606 if (delegate->paused_)
607 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700608 // Update the task id with the new scheduled callback.
609 *my_id = MessageLoop::current()->PostDelayedTask(
610 FROM_HERE,
611 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
612 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000613}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700614} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000615
616TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800617 PausingHttpFetcherTestDelegate delegate;
618 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
619 delegate.paused_ = false;
620 delegate.fetcher_ = fetcher.get();
621 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000622
Alex Deymof2858572016-02-25 11:20:13 -0800623 unique_ptr<HttpServer> server(this->test_.CreateServer());
624 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800625
Alex Deymof2858572016-02-25 11:20:13 -0800626 MessageLoop::TaskId callback_id;
627 callback_id = this->loop_.PostDelayedTask(
628 FROM_HERE,
629 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
630 base::TimeDelta::FromMilliseconds(200));
631 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000632
Alex Deymof2858572016-02-25 11:20:13 -0800633 this->loop_.Run();
634 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
635}
636
637// This test will pause the fetcher while the download is not yet started
638// because it is waiting for the proxy to be resolved.
639TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700640 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymof2858572016-02-25 11:20:13 -0800641 return;
642 MockProxyResolver mock_resolver;
643 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
644
645 // Saved arguments from the proxy call.
Alex Deymo35821942017-02-05 04:36:02 +0000646 ProxiesResolvedFn proxy_callback;
647 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _))
648 .WillOnce(DoAll(SaveArg<1>(&proxy_callback), Return(true)));
Alex Deymof2858572016-02-25 11:20:13 -0800649 fetcher->BeginTransfer("http://fake_url");
650 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
651
652 // Pausing and unpausing while resolving the proxy should not affect anything.
653 fetcher->Pause();
654 fetcher->Unpause();
655 fetcher->Pause();
656 // Proxy resolver comes back after we paused the fetcher.
Alex Deymoc00ec562017-02-05 04:36:02 +0000657 ASSERT_FALSE(proxy_callback.is_null());
Alex Deymo35821942017-02-05 04:36:02 +0000658 proxy_callback.Run({1, kNoProxy});
rspangler@google.com49fdf182009-10-10 00:57:34 +0000659}
660
661namespace {
662class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
663 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700664 bool ReceivedBytes(HttpFetcher* fetcher,
665 const void* bytes,
666 size_t length) override {
667 return true;
668 }
Alex Deymo610277e2014-11-11 21:18:11 -0800669 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800670 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700671 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000672 }
Alex Deymo610277e2014-11-11 21:18:11 -0800673 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800674 EXPECT_EQ(fetcher, fetcher_.get());
675 EXPECT_FALSE(once_);
676 EXPECT_TRUE(callback_once_);
677 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700678 // The fetcher could have a callback scheduled on the ProxyResolver that
679 // can fire after this callback. We wait until the end of the test to
680 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800681 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000682 void TerminateTransfer() {
683 CHECK(once_);
684 once_ = false;
685 fetcher_->TerminateTransfer();
686 }
Amin Hassanib2689592019-01-13 17:04:28 -0800687 void EndLoop() { MessageLoop::current()->BreakLoop(); }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000688 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800689 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700690 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000691};
692
Alex Deymo60ca1a72015-06-18 18:19:15 -0700693void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
694 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000695 if (delegate->once_) {
696 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700697 *my_id = MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800698 FROM_HERE, base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000699 } else {
700 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700701 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000702 }
703}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700704} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000705
706TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700707 AbortingHttpFetcherTestDelegate delegate;
708 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
709 delegate.once_ = true;
710 delegate.callback_once_ = true;
711 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000712
Alex Deymo60ca1a72015-06-18 18:19:15 -0700713 unique_ptr<HttpServer> server(this->test_.CreateServer());
714 this->test_.IgnoreServerAborting(server.get());
715 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800716
Alex Deymo60ca1a72015-06-18 18:19:15 -0700717 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000718
Alex Deymo60ca1a72015-06-18 18:19:15 -0700719 task_id = this->loop_.PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -0800720 FROM_HERE, base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700721 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
722
723 this->loop_.Run();
724 CHECK(!delegate.once_);
725 CHECK(!delegate.callback_once_);
726 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000727}
728
Alex Deymo71f67622017-02-03 21:30:24 -0800729TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
730 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
731 return;
732 MockProxyResolver mock_resolver;
733 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
734
735 HttpFetcherTestDelegate delegate;
736 fetcher->set_delegate(&delegate);
737
738 EXPECT_CALL(mock_resolver, GetProxiesForUrl(_, _)).WillOnce(Return(123));
739 fetcher->BeginTransfer("http://fake_url");
740 // Run the message loop until idle. This must call the MockProxyResolver with
741 // the request.
742 while (this->loop_.RunOnce(false)) {
743 }
744 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
745
746 EXPECT_CALL(mock_resolver, CancelProxyRequest(123)).WillOnce(Return(true));
747
748 // Terminate the transfer right before the proxy resolution response.
749 fetcher->TerminateTransfer();
750 EXPECT_EQ(0, delegate.times_received_bytes_called_);
751 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
752 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
753}
754
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000755namespace {
756class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
757 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700758 bool ReceivedBytes(HttpFetcher* fetcher,
759 const void* bytes,
760 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800761 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700762 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000763 }
Alex Deymo610277e2014-11-11 21:18:11 -0800764 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700765 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800766 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700767 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000768 }
Amin Hassanib2689592019-01-13 17:04:28 -0800769 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000770 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000771};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700772} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000773
774TYPED_TEST(HttpFetcherTest, FlakyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700775 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000776 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000777 {
778 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700779 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000780 fetcher->set_delegate(&delegate);
781
Ben Chan02f7c1d2014-10-18 15:18:02 -0700782 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800783 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000784
Amin Hassanib2689592019-01-13 17:04:28 -0800785 this->loop_.PostTask(FROM_HERE,
786 base::Bind(&StartTransfer,
787 fetcher.get(),
788 LocalServerUrlForPath(
789 server->GetPort(),
790 base::StringPrintf("/flaky/%d/%d/%d/%d",
791 kBigLength,
792 kFlakyTruncateLength,
793 kFlakySleepEvery,
794 kFlakySleepSecs))));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700795 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000796
797 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800798 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800799 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000800 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
801 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
802 }
803 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000804}
805
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700806namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700807// This delegate kills the server attached to it after receiving any bytes.
808// This can be used for testing what happens when you try to fetch data and
809// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700810class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
811 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700812 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700813 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700814
Alex Deymo610277e2014-11-11 21:18:11 -0800815 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700816 if (server_) {
817 LOG(INFO) << "Stopping server in destructor";
Alex Deymob20de692017-02-05 07:47:37 +0000818 server_.reset();
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700819 LOG(INFO) << "server stopped";
820 }
821 }
822
Amin Hassani0cd9d772018-07-31 23:55:43 -0700823 bool ReceivedBytes(HttpFetcher* fetcher,
824 const void* bytes,
825 size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700826 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700827 LOG(INFO) << "Stopping server in ReceivedBytes";
Alex Deymob20de692017-02-05 07:47:37 +0000828 server_.reset();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700829 LOG(INFO) << "server stopped";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700830 }
Amin Hassani0cd9d772018-07-31 23:55:43 -0700831 return true;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700832 }
Alex Deymo610277e2014-11-11 21:18:11 -0800833 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700834 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700835 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymob20de692017-02-05 07:47:37 +0000836 times_transfer_complete_called_++;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700837 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700838 }
Alex Deymo610277e2014-11-11 21:18:11 -0800839 void TransferTerminated(HttpFetcher* fetcher) override {
Alex Deymob20de692017-02-05 07:47:37 +0000840 times_transfer_terminated_called_++;
841 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800842 }
Alex Deymob20de692017-02-05 07:47:37 +0000843 unique_ptr<PythonHttpServer> server_;
844 int times_transfer_terminated_called_{0};
845 int times_transfer_complete_called_{0};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700846};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700847} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700848
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700849TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700850 // This test ensures that a fetcher responds correctly when a server isn't
851 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800852 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700853 return;
Alex Deymob20de692017-02-05 07:47:37 +0000854 FailureHttpFetcherTestDelegate delegate(nullptr);
855 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
856 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700857
Alex Deymob20de692017-02-05 07:47:37 +0000858 this->loop_.PostTask(
859 FROM_HERE,
860 base::Bind(
861 StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
862 this->loop_.Run();
863 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
864 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700865
Alex Deymob20de692017-02-05 07:47:37 +0000866 // Exiting and testing happens in the delegate
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700867}
868
Alex Deymof123ae22015-09-24 14:59:43 -0700869TYPED_TEST(HttpFetcherTest, NoResponseTest) {
870 // This test starts a new http server but the server doesn't respond and just
871 // closes the connection.
872 if (this->test_.IsMock())
873 return;
874
875 PythonHttpServer* server = new PythonHttpServer();
876 int port = server->GetPort();
877 ASSERT_TRUE(server->started_);
878
879 // Handles destruction and claims ownership.
880 FailureHttpFetcherTestDelegate delegate(server);
881 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
882 fetcher->set_delegate(&delegate);
883 // The server will not reply at all, so we can limit the execution time of the
884 // test by reducing the low-speed timeout to something small. The test will
885 // finish once the TimeoutCallback() triggers (every second) and the timeout
886 // expired.
887 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
888
Amin Hassanib2689592019-01-13 17:04:28 -0800889 this->loop_.PostTask(
890 FROM_HERE,
891 base::Bind(
892 StartTransfer, fetcher.get(), LocalServerUrlForPath(port, "/hang")));
Alex Deymof123ae22015-09-24 14:59:43 -0700893 this->loop_.Run();
Alex Deymob20de692017-02-05 07:47:37 +0000894 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
895 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Alex Deymof123ae22015-09-24 14:59:43 -0700896
897 // Check that no other callback runs in the next two seconds. That would
898 // indicate a leaked callback.
899 bool timeout = false;
Luis Hector Chavezf1cf3482016-07-19 14:29:19 -0700900 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
901 base::Unretained(&timeout));
Amin Hassanib2689592019-01-13 17:04:28 -0800902 this->loop_.PostDelayedTask(
903 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
Alex Deymof123ae22015-09-24 14:59:43 -0700904 EXPECT_TRUE(this->loop_.RunOnce(true));
905 EXPECT_TRUE(timeout);
906}
907
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700908TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700909 // This test starts a new http server and kills it after receiving its first
910 // set of bytes. It test whether or not our fetcher eventually gives up on
911 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800912 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700913 return;
Alex Deymob20de692017-02-05 07:47:37 +0000914 PythonHttpServer* server = new PythonHttpServer();
915 int port = server->GetPort();
916 ASSERT_TRUE(server->started_);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700917
Alex Deymob20de692017-02-05 07:47:37 +0000918 // Handles destruction and claims ownership.
919 FailureHttpFetcherTestDelegate delegate(server);
920 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
921 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700922
Alex Deymob20de692017-02-05 07:47:37 +0000923 this->loop_.PostTask(
924 FROM_HERE,
925 base::Bind(StartTransfer,
926 fetcher.get(),
927 LocalServerUrlForPath(port,
928 base::StringPrintf("/flaky/%d/%d/%d/%d",
929 kBigLength,
930 kFlakyTruncateLength,
931 kFlakySleepEvery,
932 kFlakySleepSecs))));
933 this->loop_.Run();
934 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
935 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700936
Alex Deymob20de692017-02-05 07:47:37 +0000937 // Exiting and testing happens in the delegate
938}
939
940// Test that we can cancel a transfer while it is still trying to connect to the
941// server. This test kills the server after a few bytes are received.
942TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
943 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
944 return;
945
946 PythonHttpServer* server = new PythonHttpServer();
947 int port = server->GetPort();
948 ASSERT_TRUE(server->started_);
949
950 // Handles destruction and claims ownership.
951 FailureHttpFetcherTestDelegate delegate(server);
952 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
953 fetcher->set_delegate(&delegate);
954
955 this->loop_.PostTask(
956 FROM_HERE,
957 base::Bind(StartTransfer,
958 fetcher.get(),
959 LocalServerUrlForPath(port,
960 base::StringPrintf("/flaky/%d/%d/%d/%d",
961 kBigLength,
962 kFlakyTruncateLength,
963 kFlakySleepEvery,
964 kFlakySleepSecs))));
965 // Terminating the transfer after 3 seconds gives it a chance to contact the
966 // server and enter the retry loop.
967 this->loop_.PostDelayedTask(FROM_HERE,
968 base::Bind(&HttpFetcher::TerminateTransfer,
969 base::Unretained(fetcher.get())),
970 base::TimeDelta::FromSeconds(3));
971
972 // Exiting and testing happens in the delegate.
973 this->loop_.Run();
974 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
975 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
976
977 // Check that no other callback runs in the next two seconds. That would
978 // indicate a leaked callback.
979 bool timeout = false;
980 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
981 base::Unretained(&timeout));
982 this->loop_.PostDelayedTask(
983 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
984 EXPECT_TRUE(this->loop_.RunOnce(true));
985 EXPECT_TRUE(timeout);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700986}
987
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700988namespace {
Amin Hassanib2689592019-01-13 17:04:28 -0800989const HttpResponseCode kRedirectCodes[] = {kHttpResponseMovedPermanently,
990 kHttpResponseFound,
991 kHttpResponseSeeOther,
992 kHttpResponseTempRedirect};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700993
994class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
995 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700996 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700997 : expected_successful_(expected_successful) {}
Amin Hassani0cd9d772018-07-31 23:55:43 -0700998 bool ReceivedBytes(HttpFetcher* fetcher,
999 const void* bytes,
1000 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001001 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001002 return true;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001003 }
Alex Deymo610277e2014-11-11 21:18:11 -08001004 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001005 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001006 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001007 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001008 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001009 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
1010 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -07001011 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001012 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001013 }
Amin Hassanib2689592019-01-13 17:04:28 -08001014 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001015 bool expected_successful_;
1016 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001017};
1018
1019// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001020void RedirectTest(const HttpServer* server,
1021 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001022 const string& url,
1023 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001024 RedirectHttpFetcherTestDelegate delegate(expected_successful);
1025 unique_ptr<HttpFetcher> fetcher(http_fetcher);
1026 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001027
Amin Hassanib2689592019-01-13 17:04:28 -08001028 MessageLoop::current()->PostTask(
1029 FROM_HERE,
1030 base::Bind(StartTransfer,
1031 fetcher.get(),
1032 LocalServerUrlForPath(server->GetPort(), url)));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001033 MessageLoop::current()->Run();
1034 if (expected_successful) {
1035 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -08001036 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -07001037 for (int i = 0; i < kMediumLength; i += 10) {
1038 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
1039 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001040 }
1041 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001042}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001043} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001044
1045TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001046 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001047 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001048
Ben Chan02f7c1d2014-10-18 15:18:02 -07001049 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001050 ASSERT_TRUE(server->started_);
1051
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001052 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Amin Hassanib2689592019-01-13 17:04:28 -08001053 const string url = base::StringPrintf(
1054 "/redirect/%d/download/%d", kRedirectCodes[c], kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001055 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001056 }
1057}
1058
1059TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001060 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001061 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001062
Ben Chan02f7c1d2014-10-18 15:18:02 -07001063 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001064 ASSERT_TRUE(server->started_);
1065
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001066 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001067 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001068 url += base::StringPrintf("/redirect/%d",
1069 kRedirectCodes[r % arraysize(kRedirectCodes)]);
1070 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001071 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001072 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001073}
1074
1075TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001076 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001077 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001078
Ben Chan02f7c1d2014-10-18 15:18:02 -07001079 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001080 ASSERT_TRUE(server->started_);
1081
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001082 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001083 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001084 url += base::StringPrintf("/redirect/%d",
1085 kRedirectCodes[r % arraysize(kRedirectCodes)]);
1086 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001087 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001088 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001089}
1090
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001091namespace {
1092class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1093 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001094 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001095 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001096
Amin Hassani0cd9d772018-07-31 23:55:43 -07001097 bool ReceivedBytes(HttpFetcher* fetcher,
1098 const void* bytes,
1099 size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001100 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001101 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001102 return true;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001103 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001104
Alex Deymo610277e2014-11-11 21:18:11 -08001105 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001106 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001107 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001108 if (expected_response_code_ != 0)
1109 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001110 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -07001111 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001112 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001113 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001114
Amin Hassanib2689592019-01-13 17:04:28 -08001115 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001116
Ben Chan02f7c1d2014-10-18 15:18:02 -07001117 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001118 int expected_response_code_;
1119 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001120};
1121
1122void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -03001123 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001124 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -07001125 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001126 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -08001127 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001128 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001129 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1130 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001131
Alex Deymo60ca1a72015-06-18 18:19:15 -07001132 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -08001133 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001134 ASSERT_TRUE(multi_fetcher);
1135 multi_fetcher->ClearRanges();
1136 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
Amin Hassanib2689592019-01-13 17:04:28 -08001137 e = ranges.end();
1138 it != e;
1139 ++it) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001140 string tmp_str = base::StringPrintf("%jd+", it->first);
1141 if (it->second > 0) {
1142 base::StringAppendF(&tmp_str, "%jd", it->second);
1143 multi_fetcher->AddRange(it->first, it->second);
1144 } else {
1145 base::StringAppendF(&tmp_str, "?");
1146 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001147 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001148 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001149 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001150 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001151 multi_fetcher->set_delegate(&delegate);
1152
1153 MessageLoop::current()->PostTask(
Amin Hassanib2689592019-01-13 17:04:28 -08001154 FROM_HERE, base::Bind(StartTransfer, multi_fetcher, url));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001155 MessageLoop::current()->Run();
1156
1157 EXPECT_EQ(expected_size, delegate.data.size());
1158 EXPECT_EQ(expected_prefix,
1159 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001160}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001161} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001162
Darin Petkov9ce452b2010-11-17 14:33:28 -08001163TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001164 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001165 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001166
Ben Chan02f7c1d2014-10-18 15:18:02 -07001167 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001168 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001169
Ben Chanf9cb98c2014-09-21 18:31:30 -07001170 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001171 ranges.push_back(make_pair(0, 25));
Tao Bao642b32b2019-01-02 15:33:42 -08001172 ranges.push_back(make_pair(99, 17));
1173 MultiTest(this->test_.NewLargeFetcher(),
1174 this->test_.fake_hardware(),
1175 this->test_.BigUrl(server->GetPort()),
1176 ranges,
1177 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1178 25 + 17,
1179 this->test_.IsFileFetcher() ? kHttpResponseOk
1180 : kHttpResponsePartialContent);
1181}
1182
1183TYPED_TEST(HttpFetcherTest, MultiHttpFetcherUnspecifiedEndTest) {
1184 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1185 return;
1186
1187 unique_ptr<HttpServer> server(this->test_.CreateServer());
1188 ASSERT_TRUE(server->started_);
1189
1190 vector<pair<off_t, off_t>> ranges;
1191 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001192 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001193 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001194 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001195 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001196 ranges,
1197 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001198 kBigLength - (99 - 25),
1199 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001200}
1201
1202TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001203 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001204 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001205
Ben Chan02f7c1d2014-10-18 15:18:02 -07001206 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001207 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001208
Ben Chanf9cb98c2014-09-21 18:31:30 -07001209 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001210 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001211 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001212 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001213 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001214 ranges,
1215 "abcdefghijabcdefghijabcd",
1216 24,
Tao Bao642b32b2019-01-02 15:33:42 -08001217 this->test_.IsFileFetcher() ? kHttpResponseOk
1218 : kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001219}
1220
1221TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001222 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001223 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001224
Ben Chan02f7c1d2014-10-18 15:18:02 -07001225 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001226 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001227
Ben Chanf9cb98c2014-09-21 18:31:30 -07001228 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001229 ranges.push_back(make_pair(kBigLength - 2, 0));
1230 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001231 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001232 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001233 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001234 ranges,
1235 "ijhij",
1236 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001237 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001238}
1239
1240TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001241 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001242 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001243
Ben Chan02f7c1d2014-10-18 15:18:02 -07001244 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001245 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001246
Ben Chanf9cb98c2014-09-21 18:31:30 -07001247 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001248 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001249 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001250 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001251 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001252 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001253 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001254 ranges,
1255 "ij",
1256 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001257 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001258 ranges.push_back(make_pair(0, 5));
1259 }
1260}
1261
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001262// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1263// should retry with other proxies listed before giving up.
1264//
1265// (1) successful recovery: The offset fetch will fail twice but succeed with
1266// the third proxy.
1267TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001268 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001269 return;
1270
Ben Chan02f7c1d2014-10-18 15:18:02 -07001271 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001272 ASSERT_TRUE(server->started_);
1273
Ben Chanf9cb98c2014-09-21 18:31:30 -07001274 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001275 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001276 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001277 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001278 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001279 LocalServerUrlForPath(
1280 server->GetPort(),
1281 base::StringPrintf("/error-if-offset/%d/2", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001282 ranges,
1283 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1284 kBigLength - (99 - 25),
1285 kHttpResponsePartialContent);
1286}
1287
1288// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1289// fetcher will signal a (failed) completed transfer to the delegate.
1290TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
Tao Bao642b32b2019-01-02 15:33:42 -08001291 if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001292 return;
1293
Ben Chan02f7c1d2014-10-18 15:18:02 -07001294 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001295 ASSERT_TRUE(server->started_);
1296
Ben Chanf9cb98c2014-09-21 18:31:30 -07001297 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001298 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001299 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001300 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001301 this->test_.fake_hardware(),
Amin Hassanib2689592019-01-13 17:04:28 -08001302 LocalServerUrlForPath(
1303 server->GetPort(),
1304 base::StringPrintf("/error-if-offset/%d/3", kBigLength)),
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001305 ranges,
1306 "abcdefghijabcdefghijabcde", // only received the first chunk
1307 25,
1308 kHttpResponseUndefined);
1309}
1310
Alex Deymo4ea2d922017-02-05 07:35:32 +00001311namespace {
1312// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1313class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1314 public:
1315 explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1316 : terminate_trigger_bytes_(terminate_trigger_bytes) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001317
Amin Hassani0cd9d772018-07-31 23:55:43 -07001318 bool ReceivedBytes(HttpFetcher* fetcher,
Alex Deymo4ea2d922017-02-05 07:35:32 +00001319 const void* bytes,
1320 size_t length) override {
1321 LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
1322 EXPECT_EQ(fetcher, fetcher_.get());
Tao Bao642b32b2019-01-02 15:33:42 -08001323 bool should_terminate = false;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001324 if (bytes_downloaded_ < terminate_trigger_bytes_ &&
1325 bytes_downloaded_ + length >= terminate_trigger_bytes_) {
1326 MessageLoop::current()->PostTask(
1327 FROM_HERE,
1328 base::Bind(&HttpFetcher::TerminateTransfer,
1329 base::Unretained(fetcher_.get())));
Tao Bao642b32b2019-01-02 15:33:42 -08001330 should_terminate = true;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001331 }
1332 bytes_downloaded_ += length;
Tao Bao642b32b2019-01-02 15:33:42 -08001333 return !should_terminate;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001334 }
1335
1336 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1337 ADD_FAILURE() << "TransferComplete called but expected a failure";
1338 // Destroy the fetcher (because we're allowed to).
1339 fetcher_.reset(nullptr);
1340 MessageLoop::current()->BreakLoop();
1341 }
1342
1343 void TransferTerminated(HttpFetcher* fetcher) override {
1344 // Destroy the fetcher (because we're allowed to).
1345 fetcher_.reset(nullptr);
1346 MessageLoop::current()->BreakLoop();
1347 }
1348
1349 unique_ptr<HttpFetcher> fetcher_;
1350 size_t bytes_downloaded_{0};
1351 size_t terminate_trigger_bytes_;
1352};
1353} // namespace
1354
1355TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
1356 if (!this->test_.IsMulti())
1357 return;
1358 const size_t kRangeTrigger = 1000;
1359 MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
1360
1361 unique_ptr<HttpServer> server(this->test_.CreateServer());
1362 ASSERT_TRUE(server->started_);
1363
1364 MultiRangeHttpFetcher* multi_fetcher =
1365 static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
1366 ASSERT_TRUE(multi_fetcher);
1367 // Transfer ownership of the fetcher to the delegate.
1368 delegate.fetcher_.reset(multi_fetcher);
1369 multi_fetcher->set_delegate(&delegate);
1370
1371 multi_fetcher->ClearRanges();
1372 multi_fetcher->AddRange(45, kRangeTrigger);
1373 multi_fetcher->AddRange(2000, 100);
1374
1375 this->test_.fake_hardware()->SetIsOfficialBuild(false);
1376
1377 StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
1378 MessageLoop::current()->Run();
1379
1380 // Check that the delegate made it to the trigger point.
1381 EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
1382}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001383
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001384namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001385class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001386 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -07001387 bool ReceivedBytes(HttpFetcher* fetcher,
1388 const void* bytes,
1389 size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001390 ADD_FAILURE();
Amin Hassani0cd9d772018-07-31 23:55:43 -07001391 return true;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001392 }
Alex Deymo610277e2014-11-11 21:18:11 -08001393 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001394 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001395 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001396 }
Amin Hassanib2689592019-01-13 17:04:28 -08001397 void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001398};
1399
Alex Deymo60ca1a72015-06-18 18:19:15 -07001400void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1401 bool is_official_build) {
1402 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1403 return;
1404
1405 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1406 ASSERT_TRUE(server->started_);
1407
1408 BlockedTransferTestDelegate delegate;
1409 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1410 LOG(INFO) << "is_official_build: " << is_official_build;
1411 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001412 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001413 fetcher->set_delegate(&delegate);
1414
Amin Hassanib2689592019-01-13 17:04:28 -08001415 MessageLoop::current()->PostTask(
1416 FROM_HERE,
1417 base::Bind(
1418 StartTransfer,
1419 fetcher.get(),
1420 LocalServerUrlForPath(server->GetPort(),
1421 fetcher_test->SmallUrl(server->GetPort()))));
Alex Deymo60ca1a72015-06-18 18:19:15 -07001422 MessageLoop::current()->Run();
1423}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001424} // namespace
1425
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001426TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001427 BlockedTransferTestHelper(&this->test_, false);
1428}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001429
Alex Deymo60ca1a72015-06-18 18:19:15 -07001430TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1431 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001432}
1433
rspangler@google.com49fdf182009-10-10 00:57:34 +00001434} // namespace chromeos_update_engine