blob: a0b0522385ed4d8bf5e417995beff8aa57c978f5 [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
Ben Chan02f7c1d2014-10-18 15:18:02 -070022#include <memory>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000023#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070024#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000025#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070026
Alex Deymo706a5ab2015-11-23 17:48:30 -030027#include <base/bind.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070028#include <base/location.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080029#include <base/logging.h>
Alex Deymo535f3b72015-08-07 10:51:32 -070030#include <base/message_loop/message_loop.h>
31#include <base/strings/string_number_conversions.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070032#include <base/strings/string_util.h>
33#include <base/strings/stringprintf.h>
34#include <base/time/time.h>
Amin Hassani71818c82018-03-06 13:25:40 -080035#include <brillo/bind_lambda.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"
48#include "update_engine/common/multi_range_http_fetcher.h"
49#include "update_engine/common/test_utils.h"
50#include "update_engine/common/utils.h"
Alex Deymo14c0da82016-07-20 16:45:45 -070051#include "update_engine/libcurl_http_fetcher.h"
Alex Deymof2858572016-02-25 11:20:13 -080052#include "update_engine/mock_proxy_resolver.h"
Andrew de los Reyes45168102010-11-22 11:13:50 -080053#include "update_engine/proxy_resolver.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;
Alex Deymof2858572016-02-25 11:20:13 -080061using testing::DoAll;
62using testing::Return;
63using testing::SaveArg;
64using testing::_;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000065
Gilad Arnold9bedeb52011-11-17 16:19:57 -080066namespace {
67
68const int kBigLength = 100000;
69const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080070const int kFlakyTruncateLength = 29000;
71const int kFlakySleepEvery = 3;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080072const int kFlakySleepSecs = 10;
73
74} // namespace
75
rspangler@google.com49fdf182009-10-10 00:57:34 +000076namespace chromeos_update_engine {
77
Gilad Arnold9bedeb52011-11-17 16:19:57 -080078static const char *kUnusedUrl = "unused://unused";
79
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070080static inline string LocalServerUrlForPath(in_port_t port,
81 const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070082 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070083 return base::StringPrintf("http://127.0.0.1%s%s", port_str.c_str(),
84 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
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070096 virtual in_port_t GetPort() const {
97 return 0;
98 }
99
rspangler@google.com49fdf182009-10-10 00:57:34 +0000100 bool started_;
101};
102
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800103HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000104
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800105
106class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000107 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800108 NullHttpServer() {
109 started_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000110 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000111};
112
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800113
114class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000115 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700116 PythonHttpServer() : port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000117 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700118
119 // Spawn the server process.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700120 unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
Sen Jiang260f03b2016-03-21 15:34:58 -0700121 http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
Alex Deymo535f3b72015-08-07 10:51:32 -0700122 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
123
124 if (!http_server->Start()) {
125 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000126 return;
127 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700128 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700129
130 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700131 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700132 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
133 if (!stdout)
134 return;
135
136 vector<char> buf(128);
137 string line;
138 while (line.find('\n') == string::npos) {
139 size_t read;
140 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
141 ADD_FAILURE() << "error reading http server stdout";
142 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700143 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700144 line.append(buf.data(), read);
145 if (read == 0)
146 break;
147 }
148 // Parse the port from the output line.
149 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
150 if (line.size() < listening_msg_prefix_len) {
151 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700152 return;
153 }
154
Alex Deymo535f3b72015-08-07 10:51:32 -0700155 EXPECT_EQ(kServerListeningMsgPrefix,
156 line.substr(0, listening_msg_prefix_len));
157 string port_str = line.substr(listening_msg_prefix_len);
158 port_str.resize(port_str.find('\n'));
159 EXPECT_TRUE(base::StringToUint(port_str, &port_));
160
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700161 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700162 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700163
164 // Any failure before this point will SIGKILL the test server if started
165 // when the |http_server| goes out of scope.
166 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000167 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800168
rspangler@google.com49fdf182009-10-10 00:57:34 +0000169 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700170 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700171 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000172 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700173 // Wait up to 10 seconds for the process to finish. Destroying the process
174 // will kill it with a SIGKILL otherwise.
175 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000176 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800177
Alex Deymo610277e2014-11-11 21:18:11 -0800178 in_port_t GetPort() const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700179 return port_;
180 }
181
182 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700183 static const char* kServerListeningMsgPrefix;
184
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700185 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700186 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000187};
188
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700189const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
190
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800191//
192// Class hierarchy for HTTP fetcher test wrappers.
193//
194
195class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000196 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700197 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700198 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700199
Alex Deymof2858572016-02-25 11:20:13 -0800200 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
201 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
202 proxy_resolver_.set_num_proxies(num_proxies);
203 return NewLargeFetcher(&proxy_resolver_);
204 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800205 HttpFetcher* NewLargeFetcher() {
206 return NewLargeFetcher(1);
207 }
208
Alex Deymof2858572016-02-25 11:20:13 -0800209 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800210 HttpFetcher* NewSmallFetcher() {
Alex Deymof2858572016-02-25 11:20:13 -0800211 proxy_resolver_.set_num_proxies(1);
212 return NewSmallFetcher(&proxy_resolver_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800213 }
214
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700215 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
216 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
217 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800218
219 virtual bool IsMock() const = 0;
220 virtual bool IsMulti() const = 0;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700221 virtual bool IsHttpSupported() const = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800222
223 virtual void IgnoreServerAborting(HttpServer* server) const {}
224
Alex Deymo60ca1a72015-06-18 18:19:15 -0700225 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800226
Alex Deymoc1c17b42015-11-23 03:53:15 -0300227 FakeHardware* fake_hardware() {
Alex Deymo706a5ab2015-11-23 17:48:30 -0300228 return &fake_hardware_;
Alex Deymoc1c17b42015-11-23 03:53:15 -0300229 }
230
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800231 protected:
232 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300233 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800234};
235
236class MockHttpFetcherTest : public AnyHttpFetcherTest {
237 public:
238 // Necessary to unhide the definition in the base class.
239 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800240 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700241 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800242 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800243 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800244 }
245
246 // Necessary to unhide the definition in the base class.
247 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800248 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
249 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800250 }
251
Alex Deymo610277e2014-11-11 21:18:11 -0800252 bool IsMock() const override { return true; }
253 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700254 bool IsHttpSupported() const override { return true; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800255
Alex Deymo60ca1a72015-06-18 18:19:15 -0700256 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800257 return new NullHttpServer;
258 }
259};
260
261class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
262 public:
263 // Necessary to unhide the definition in the base class.
264 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800265 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
266 LibcurlHttpFetcher* ret =
267 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700268 // Speed up test execution.
269 ret->set_idle_seconds(1);
270 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300271 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000272 return ret;
273 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800274
275 // Necessary to unhide the definition in the base class.
276 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800277 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
278 return NewLargeFetcher(proxy_resolver);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000279 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800280
Alex Deymo610277e2014-11-11 21:18:11 -0800281 string BigUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700282 return LocalServerUrlForPath(port,
283 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800284 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000285 }
Alex Deymo610277e2014-11-11 21:18:11 -0800286 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700287 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000288 }
Alex Deymo610277e2014-11-11 21:18:11 -0800289 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700290 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800291 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800292
Alex Deymo610277e2014-11-11 21:18:11 -0800293 bool IsMock() const override { return false; }
294 bool IsMulti() const override { return false; }
Alex Deymo2c131bb2016-05-26 16:43:13 -0700295 bool IsHttpSupported() const override { return true; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800296
Alex Deymo610277e2014-11-11 21:18:11 -0800297 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700298 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700299 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800300
Alex Deymo60ca1a72015-06-18 18:19:15 -0700301 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800302 return new PythonHttpServer;
303 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000304};
305
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800306class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700307 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800308 // Necessary to unhide the definition in the base class.
309 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800310 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
311 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
312 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800313 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800314 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700315 // Speed up test execution.
316 ret->set_idle_seconds(1);
317 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300318 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700319 return ret;
320 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800321
322 // Necessary to unhide the definition in the base class.
323 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800324 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
325 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800326 }
327
Alex Deymo610277e2014-11-11 21:18:11 -0800328 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700329};
330
Alex Deymo2c131bb2016-05-26 16:43:13 -0700331class FileFetcherTest : public AnyHttpFetcherTest {
332 public:
333 // Necessary to unhide the definition in the base class.
334 using AnyHttpFetcherTest::NewLargeFetcher;
335 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
336 return new FileFetcher();
337 }
338
339 // Necessary to unhide the definition in the base class.
340 using AnyHttpFetcherTest::NewSmallFetcher;
341 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
342 return NewLargeFetcher(proxy_resolver);
343 }
344
345 string BigUrl(in_port_t port) const override {
346 return "file://" + temp_file_.path();
347 }
348 string SmallUrl(in_port_t port) const override {
349 test_utils::WriteFileString(temp_file_.path(), "small contents");
350 return "file://" + temp_file_.path();
351 }
352 string ErrorUrl(in_port_t port) const override {
353 return "file:///path/to/non-existing-file";
354 }
355
356 bool IsMock() const override { return false; }
357 bool IsMulti() const override { return false; }
358 bool IsHttpSupported() const override { return false; }
359
360 void IgnoreServerAborting(HttpServer* server) const override {}
361
362 HttpServer* CreateServer() override { return new NullHttpServer; }
363
364 private:
365 test_utils::ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
366};
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800367
368//
369// Infrastructure for type tests of HTTP fetcher.
370// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
371//
372
373// Fixture class template. We use an explicit constraint to guarantee that it
374// can only be instantiated with an AnyHttpFetcherTest type, see:
375// http://www2.research.att.com/~bs/bs_faq2.html#constraints
376template <typename T>
377class HttpFetcherTest : public ::testing::Test {
378 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700379 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700380 brillo::BaseMessageLoop loop_{&base_loop_};
Alex Deymo60ca1a72015-06-18 18:19:15 -0700381
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800382 T test_;
383
Alex Deymo60ca1a72015-06-18 18:19:15 -0700384 protected:
385 HttpFetcherTest() {
386 loop_.SetAsCurrent();
387 }
388
389 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700390 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700391 }
392
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800393 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700394 static void TypeConstraint(T* a) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800395 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700396 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700397 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800398 }
399};
400
401// Test case types list.
402typedef ::testing::Types<LibcurlHttpFetcherTest,
403 MockHttpFetcherTest,
Alex Deymo2c131bb2016-05-26 16:43:13 -0700404 MultiRangeHttpFetcherTest,
405 FileFetcherTest>
406 HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000407TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
408
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800409
rspangler@google.com49fdf182009-10-10 00:57:34 +0000410namespace {
411class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000412 public:
Alex Deymofdd6dec2016-03-03 22:35:43 -0800413 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800414
Amin Hassani0cd9d772018-07-31 23:55:43 -0700415 bool ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymofdd6dec2016-03-03 22:35:43 -0800416 const void* bytes,
417 size_t length) override {
418 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800419 // Update counters
420 times_received_bytes_called_++;
Amin Hassani0cd9d772018-07-31 23:55:43 -0700421 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000422 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800423
Alex Deymo610277e2014-11-11 21:18:11 -0800424 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800425 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800426 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800427 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800428 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700429 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800430
431 // Update counter
432 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000433 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800434
Alex Deymo610277e2014-11-11 21:18:11 -0800435 void TransferTerminated(HttpFetcher* fetcher) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800436 times_transfer_terminated_called_++;
Alex Deymo2c131bb2016-05-26 16:43:13 -0700437 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800438 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800439
Gilad Arnold48085ba2011-11-16 09:36:08 -0800440 // Are we expecting an error response? (default: no)
Alex Deymofdd6dec2016-03-03 22:35:43 -0800441 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800442
443 // Counters for callback invocations.
Alex Deymofdd6dec2016-03-03 22:35:43 -0800444 int times_transfer_complete_called_{0};
445 int times_transfer_terminated_called_{0};
446 int times_received_bytes_called_{0};
447
448 // The received data bytes.
449 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000450};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000451
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000452
Alex Deymo60ca1a72015-06-18 18:19:15 -0700453void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
454 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000455}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700456} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000457
458TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700459 HttpFetcherTestDelegate delegate;
460 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
461 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000462
Alex Deymo60ca1a72015-06-18 18:19:15 -0700463 unique_ptr<HttpServer> server(this->test_.CreateServer());
464 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000465
Alex Deymo60ca1a72015-06-18 18:19:15 -0700466 this->loop_.PostTask(FROM_HERE, base::Bind(
467 StartTransfer,
468 fetcher.get(),
469 this->test_.SmallUrl(server->GetPort())));
470 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800471 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000472}
473
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700474TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700475 HttpFetcherTestDelegate delegate;
476 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
477 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700478
Alex Deymo60ca1a72015-06-18 18:19:15 -0700479 unique_ptr<HttpServer> server(this->test_.CreateServer());
480 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700481
Alex Deymo60ca1a72015-06-18 18:19:15 -0700482 this->loop_.PostTask(FROM_HERE, base::Bind(
483 StartTransfer,
484 fetcher.get(),
485 this->test_.BigUrl(server->GetPort())));
486 this->loop_.Run();
Alex Deymo71f67622017-02-03 21:30:24 -0800487 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700488}
489
Gilad Arnold48085ba2011-11-16 09:36:08 -0800490// Issue #9648: when server returns an error HTTP response, the fetcher needs to
491// terminate transfer prematurely, rather than try to process the error payload.
492TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800493 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800494 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700495 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800496
Alex Deymo60ca1a72015-06-18 18:19:15 -0700497 // Delegate should expect an error response.
498 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800499
Alex Deymo60ca1a72015-06-18 18:19:15 -0700500 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
501 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800502
Alex Deymo60ca1a72015-06-18 18:19:15 -0700503 unique_ptr<HttpServer> server(this->test_.CreateServer());
504 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800505
Alex Deymo60ca1a72015-06-18 18:19:15 -0700506 this->loop_.PostTask(FROM_HERE, base::Bind(
507 StartTransfer,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800508 fetcher.get(),
Alex Deymo60ca1a72015-06-18 18:19:15 -0700509 this->test_.ErrorUrl(server->GetPort())));
510 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800511
Alex Deymo60ca1a72015-06-18 18:19:15 -0700512 // Make sure that no bytes were received.
Alex Deymo71f67622017-02-03 21:30:24 -0800513 EXPECT_EQ(0, delegate.times_received_bytes_called_);
514 EXPECT_EQ(0U, fetcher->GetBytesDownloaded());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800515
Alex Deymo60ca1a72015-06-18 18:19:15 -0700516 // Make sure that transfer completion was signaled once, and no termination
517 // was signaled.
Alex Deymo71f67622017-02-03 21:30:24 -0800518 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
519 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800520}
521
Alex Deymofdd6dec2016-03-03 22:35:43 -0800522TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700523 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymofdd6dec2016-03-03 22:35:43 -0800524 return;
525
526 HttpFetcherTestDelegate delegate;
527 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
528 fetcher->set_delegate(&delegate);
529 fetcher->SetHeader("User-Agent", "MyTest");
530 fetcher->SetHeader("user-agent", "Override that header");
531 fetcher->SetHeader("Authorization", "Basic user:passwd");
532
533 // Invalid headers.
534 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
535 fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
536
537 // Hide Accept header normally added by default.
538 fetcher->SetHeader("Accept", "");
539
540 PythonHttpServer server;
541 int port = server.GetPort();
542 ASSERT_TRUE(server.started_);
543
Alex Deymo2c131bb2016-05-26 16:43:13 -0700544 this->loop_.PostTask(
545 FROM_HERE,
546 base::Bind(StartTransfer,
547 fetcher.get(),
548 LocalServerUrlForPath(port, "/echo-headers")));
Alex Deymofdd6dec2016-03-03 22:35:43 -0800549 this->loop_.Run();
550
551 EXPECT_NE(string::npos,
552 delegate.data.find("user-agent: Override that header\r\n"));
553 EXPECT_NE(string::npos,
554 delegate.data.find("Authorization: Basic user:passwd\r\n"));
555
556 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
557 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
558 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
559}
560
rspangler@google.com49fdf182009-10-10 00:57:34 +0000561namespace {
562class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
563 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700564 bool ReceivedBytes(HttpFetcher* fetcher,
565 const void* /* bytes */,
566 size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000567 CHECK(!paused_);
568 paused_ = true;
569 fetcher->Pause();
Amin Hassani0cd9d772018-07-31 23:55:43 -0700570 return true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000571 }
Alex Deymo610277e2014-11-11 21:18:11 -0800572 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700573 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000574 }
Alex Deymo610277e2014-11-11 21:18:11 -0800575 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800576 ADD_FAILURE();
577 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000578 void Unpause() {
579 CHECK(paused_);
580 paused_ = false;
581 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000582 }
583 bool paused_;
584 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000585};
586
Alex Deymo60ca1a72015-06-18 18:19:15 -0700587void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
588 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000589 if (delegate->paused_)
590 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700591 // Update the task id with the new scheduled callback.
592 *my_id = MessageLoop::current()->PostDelayedTask(
593 FROM_HERE,
594 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
595 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000596}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700597} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000598
599TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800600 PausingHttpFetcherTestDelegate delegate;
601 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
602 delegate.paused_ = false;
603 delegate.fetcher_ = fetcher.get();
604 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000605
Alex Deymof2858572016-02-25 11:20:13 -0800606 unique_ptr<HttpServer> server(this->test_.CreateServer());
607 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800608
Alex Deymof2858572016-02-25 11:20:13 -0800609 MessageLoop::TaskId callback_id;
610 callback_id = this->loop_.PostDelayedTask(
611 FROM_HERE,
612 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
613 base::TimeDelta::FromMilliseconds(200));
614 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000615
Alex Deymof2858572016-02-25 11:20:13 -0800616 this->loop_.Run();
617 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
618}
619
620// This test will pause the fetcher while the download is not yet started
621// because it is waiting for the proxy to be resolved.
622TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700623 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymof2858572016-02-25 11:20:13 -0800624 return;
625 MockProxyResolver mock_resolver;
626 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
627
628 // Saved arguments from the proxy call.
Alex Deymo35821942017-02-05 04:36:02 +0000629 ProxiesResolvedFn proxy_callback;
630 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _))
631 .WillOnce(DoAll(SaveArg<1>(&proxy_callback), Return(true)));
Alex Deymof2858572016-02-25 11:20:13 -0800632 fetcher->BeginTransfer("http://fake_url");
633 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
634
635 // Pausing and unpausing while resolving the proxy should not affect anything.
636 fetcher->Pause();
637 fetcher->Unpause();
638 fetcher->Pause();
639 // Proxy resolver comes back after we paused the fetcher.
Alex Deymoc00ec562017-02-05 04:36:02 +0000640 ASSERT_FALSE(proxy_callback.is_null());
Alex Deymo35821942017-02-05 04:36:02 +0000641 proxy_callback.Run({1, kNoProxy});
rspangler@google.com49fdf182009-10-10 00:57:34 +0000642}
643
644namespace {
645class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
646 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700647 bool ReceivedBytes(HttpFetcher* fetcher,
648 const void* bytes,
649 size_t length) override {
650 return true;
651 }
Alex Deymo610277e2014-11-11 21:18:11 -0800652 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800653 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700654 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000655 }
Alex Deymo610277e2014-11-11 21:18:11 -0800656 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800657 EXPECT_EQ(fetcher, fetcher_.get());
658 EXPECT_FALSE(once_);
659 EXPECT_TRUE(callback_once_);
660 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700661 // The fetcher could have a callback scheduled on the ProxyResolver that
662 // can fire after this callback. We wait until the end of the test to
663 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800664 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000665 void TerminateTransfer() {
666 CHECK(once_);
667 once_ = false;
668 fetcher_->TerminateTransfer();
669 }
670 void EndLoop() {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700671 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000672 }
673 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800674 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700675 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000676};
677
Alex Deymo60ca1a72015-06-18 18:19:15 -0700678void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
679 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000680 if (delegate->once_) {
681 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700682 *my_id = MessageLoop::current()->PostTask(
683 FROM_HERE,
684 base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000685 } else {
686 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700687 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000688 }
689}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700690} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000691
692TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700693 AbortingHttpFetcherTestDelegate delegate;
694 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
695 delegate.once_ = true;
696 delegate.callback_once_ = true;
697 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000698
Alex Deymo60ca1a72015-06-18 18:19:15 -0700699 unique_ptr<HttpServer> server(this->test_.CreateServer());
700 this->test_.IgnoreServerAborting(server.get());
701 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800702
Alex Deymo60ca1a72015-06-18 18:19:15 -0700703 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000704
Alex Deymo60ca1a72015-06-18 18:19:15 -0700705 task_id = this->loop_.PostTask(
706 FROM_HERE,
707 base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
708 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
709
710 this->loop_.Run();
711 CHECK(!delegate.once_);
712 CHECK(!delegate.callback_once_);
713 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000714}
715
Alex Deymo71f67622017-02-03 21:30:24 -0800716TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
717 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
718 return;
719 MockProxyResolver mock_resolver;
720 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
721
722 HttpFetcherTestDelegate delegate;
723 fetcher->set_delegate(&delegate);
724
725 EXPECT_CALL(mock_resolver, GetProxiesForUrl(_, _)).WillOnce(Return(123));
726 fetcher->BeginTransfer("http://fake_url");
727 // Run the message loop until idle. This must call the MockProxyResolver with
728 // the request.
729 while (this->loop_.RunOnce(false)) {
730 }
731 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
732
733 EXPECT_CALL(mock_resolver, CancelProxyRequest(123)).WillOnce(Return(true));
734
735 // Terminate the transfer right before the proxy resolution response.
736 fetcher->TerminateTransfer();
737 EXPECT_EQ(0, delegate.times_received_bytes_called_);
738 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
739 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
740}
741
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000742namespace {
743class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
744 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -0700745 bool ReceivedBytes(HttpFetcher* fetcher,
746 const void* bytes,
747 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800748 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700749 return true;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000750 }
Alex Deymo610277e2014-11-11 21:18:11 -0800751 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700752 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800753 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700754 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000755 }
Alex Deymo610277e2014-11-11 21:18:11 -0800756 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800757 ADD_FAILURE();
758 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000759 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000760};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700761} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000762
763TYPED_TEST(HttpFetcherTest, FlakyTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -0700764 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000765 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000766 {
767 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700768 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000769 fetcher->set_delegate(&delegate);
770
Ben Chan02f7c1d2014-10-18 15:18:02 -0700771 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800772 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000773
Alex Deymo60ca1a72015-06-18 18:19:15 -0700774 this->loop_.PostTask(FROM_HERE, base::Bind(
775 &StartTransfer,
776 fetcher.get(),
777 LocalServerUrlForPath(server->GetPort(),
778 base::StringPrintf("/flaky/%d/%d/%d/%d",
779 kBigLength,
780 kFlakyTruncateLength,
781 kFlakySleepEvery,
782 kFlakySleepSecs))));
783 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000784
785 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800786 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800787 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000788 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
789 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
790 }
791 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000792}
793
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700794namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700795// This delegate kills the server attached to it after receiving any bytes.
796// This can be used for testing what happens when you try to fetch data and
797// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700798class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
799 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700800 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700801 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700802
Alex Deymo610277e2014-11-11 21:18:11 -0800803 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700804 if (server_) {
805 LOG(INFO) << "Stopping server in destructor";
Alex Deymob20de692017-02-05 07:47:37 +0000806 server_.reset();
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700807 LOG(INFO) << "server stopped";
808 }
809 }
810
Amin Hassani0cd9d772018-07-31 23:55:43 -0700811 bool ReceivedBytes(HttpFetcher* fetcher,
812 const void* bytes,
813 size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700814 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700815 LOG(INFO) << "Stopping server in ReceivedBytes";
Alex Deymob20de692017-02-05 07:47:37 +0000816 server_.reset();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700817 LOG(INFO) << "server stopped";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700818 }
Amin Hassani0cd9d772018-07-31 23:55:43 -0700819 return true;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700820 }
Alex Deymo610277e2014-11-11 21:18:11 -0800821 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700822 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700823 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymob20de692017-02-05 07:47:37 +0000824 times_transfer_complete_called_++;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700825 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700826 }
Alex Deymo610277e2014-11-11 21:18:11 -0800827 void TransferTerminated(HttpFetcher* fetcher) override {
Alex Deymob20de692017-02-05 07:47:37 +0000828 times_transfer_terminated_called_++;
829 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800830 }
Alex Deymob20de692017-02-05 07:47:37 +0000831 unique_ptr<PythonHttpServer> server_;
832 int times_transfer_terminated_called_{0};
833 int times_transfer_complete_called_{0};
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700834};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700835} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700836
837
838TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700839 // This test ensures that a fetcher responds correctly when a server isn't
840 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800841 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700842 return;
Alex Deymob20de692017-02-05 07:47:37 +0000843 FailureHttpFetcherTestDelegate delegate(nullptr);
844 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
845 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700846
Alex Deymob20de692017-02-05 07:47:37 +0000847 this->loop_.PostTask(
848 FROM_HERE,
849 base::Bind(
850 StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
851 this->loop_.Run();
852 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
853 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700854
Alex Deymob20de692017-02-05 07:47:37 +0000855 // Exiting and testing happens in the delegate
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700856}
857
Alex Deymof123ae22015-09-24 14:59:43 -0700858TYPED_TEST(HttpFetcherTest, NoResponseTest) {
859 // This test starts a new http server but the server doesn't respond and just
860 // closes the connection.
861 if (this->test_.IsMock())
862 return;
863
864 PythonHttpServer* server = new PythonHttpServer();
865 int port = server->GetPort();
866 ASSERT_TRUE(server->started_);
867
868 // Handles destruction and claims ownership.
869 FailureHttpFetcherTestDelegate delegate(server);
870 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
871 fetcher->set_delegate(&delegate);
872 // The server will not reply at all, so we can limit the execution time of the
873 // test by reducing the low-speed timeout to something small. The test will
874 // finish once the TimeoutCallback() triggers (every second) and the timeout
875 // expired.
876 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
877
878 this->loop_.PostTask(FROM_HERE, base::Bind(
879 StartTransfer,
880 fetcher.get(),
881 LocalServerUrlForPath(port, "/hang")));
882 this->loop_.Run();
Alex Deymob20de692017-02-05 07:47:37 +0000883 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
884 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Alex Deymof123ae22015-09-24 14:59:43 -0700885
886 // Check that no other callback runs in the next two seconds. That would
887 // indicate a leaked callback.
888 bool timeout = false;
Luis Hector Chavezf1cf3482016-07-19 14:29:19 -0700889 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
890 base::Unretained(&timeout));
Alex Deymof123ae22015-09-24 14:59:43 -0700891 this->loop_.PostDelayedTask(FROM_HERE, callback,
892 base::TimeDelta::FromSeconds(2));
893 EXPECT_TRUE(this->loop_.RunOnce(true));
894 EXPECT_TRUE(timeout);
895}
896
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700897TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700898 // This test starts a new http server and kills it after receiving its first
899 // set of bytes. It test whether or not our fetcher eventually gives up on
900 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800901 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700902 return;
Alex Deymob20de692017-02-05 07:47:37 +0000903 PythonHttpServer* server = new PythonHttpServer();
904 int port = server->GetPort();
905 ASSERT_TRUE(server->started_);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700906
Alex Deymob20de692017-02-05 07:47:37 +0000907 // Handles destruction and claims ownership.
908 FailureHttpFetcherTestDelegate delegate(server);
909 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
910 fetcher->set_delegate(&delegate);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700911
Alex Deymob20de692017-02-05 07:47:37 +0000912 this->loop_.PostTask(
913 FROM_HERE,
914 base::Bind(StartTransfer,
915 fetcher.get(),
916 LocalServerUrlForPath(port,
917 base::StringPrintf("/flaky/%d/%d/%d/%d",
918 kBigLength,
919 kFlakyTruncateLength,
920 kFlakySleepEvery,
921 kFlakySleepSecs))));
922 this->loop_.Run();
923 EXPECT_EQ(1, delegate.times_transfer_complete_called_);
924 EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700925
Alex Deymob20de692017-02-05 07:47:37 +0000926 // Exiting and testing happens in the delegate
927}
928
929// Test that we can cancel a transfer while it is still trying to connect to the
930// server. This test kills the server after a few bytes are received.
931TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
932 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
933 return;
934
935 PythonHttpServer* server = new PythonHttpServer();
936 int port = server->GetPort();
937 ASSERT_TRUE(server->started_);
938
939 // Handles destruction and claims ownership.
940 FailureHttpFetcherTestDelegate delegate(server);
941 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
942 fetcher->set_delegate(&delegate);
943
944 this->loop_.PostTask(
945 FROM_HERE,
946 base::Bind(StartTransfer,
947 fetcher.get(),
948 LocalServerUrlForPath(port,
949 base::StringPrintf("/flaky/%d/%d/%d/%d",
950 kBigLength,
951 kFlakyTruncateLength,
952 kFlakySleepEvery,
953 kFlakySleepSecs))));
954 // Terminating the transfer after 3 seconds gives it a chance to contact the
955 // server and enter the retry loop.
956 this->loop_.PostDelayedTask(FROM_HERE,
957 base::Bind(&HttpFetcher::TerminateTransfer,
958 base::Unretained(fetcher.get())),
959 base::TimeDelta::FromSeconds(3));
960
961 // Exiting and testing happens in the delegate.
962 this->loop_.Run();
963 EXPECT_EQ(0, delegate.times_transfer_complete_called_);
964 EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
965
966 // Check that no other callback runs in the next two seconds. That would
967 // indicate a leaked callback.
968 bool timeout = false;
969 auto callback = base::Bind([](bool* timeout) { *timeout = true; },
970 base::Unretained(&timeout));
971 this->loop_.PostDelayedTask(
972 FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
973 EXPECT_TRUE(this->loop_.RunOnce(true));
974 EXPECT_TRUE(timeout);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700975}
976
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700977namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800978const HttpResponseCode kRedirectCodes[] = {
979 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
980 kHttpResponseTempRedirect
981};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700982
983class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
984 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700985 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700986 : expected_successful_(expected_successful) {}
Amin Hassani0cd9d772018-07-31 23:55:43 -0700987 bool ReceivedBytes(HttpFetcher* fetcher,
988 const void* bytes,
989 size_t length) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800990 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -0700991 return true;
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700992 }
Alex Deymo610277e2014-11-11 21:18:11 -0800993 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700994 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700995 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800996 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700997 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800998 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
999 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -07001000 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001001 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001002 }
Alex Deymo610277e2014-11-11 21:18:11 -08001003 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001004 ADD_FAILURE();
1005 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001006 bool expected_successful_;
1007 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001008};
1009
1010// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001011void RedirectTest(const HttpServer* server,
1012 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001013 const string& url,
1014 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001015 RedirectHttpFetcherTestDelegate delegate(expected_successful);
1016 unique_ptr<HttpFetcher> fetcher(http_fetcher);
1017 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001018
Alex Deymo60ca1a72015-06-18 18:19:15 -07001019 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1020 StartTransfer,
1021 fetcher.get(),
1022 LocalServerUrlForPath(server->GetPort(), url)));
1023 MessageLoop::current()->Run();
1024 if (expected_successful) {
1025 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -08001026 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -07001027 for (int i = 0; i < kMediumLength; i += 10) {
1028 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
1029 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001030 }
1031 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001032}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001033} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001034
1035TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001036 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001037 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001038
Ben Chan02f7c1d2014-10-18 15:18:02 -07001039 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001040 ASSERT_TRUE(server->started_);
1041
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001042 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001043 const string url = base::StringPrintf("/redirect/%d/download/%d",
1044 kRedirectCodes[c],
1045 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001046 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001047 }
1048}
1049
1050TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001051 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001052 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001053
Ben Chan02f7c1d2014-10-18 15:18:02 -07001054 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001055 ASSERT_TRUE(server->started_);
1056
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001057 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001058 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001059 url += base::StringPrintf("/redirect/%d",
1060 kRedirectCodes[r % arraysize(kRedirectCodes)]);
1061 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001062 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001063 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001064}
1065
1066TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Alex Deymo2c131bb2016-05-26 16:43:13 -07001067 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001068 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001069
Ben Chan02f7c1d2014-10-18 15:18:02 -07001070 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001071 ASSERT_TRUE(server->started_);
1072
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001073 string url;
David Zeuthen34135a92013-08-06 11:16:16 -07001074 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001075 url += base::StringPrintf("/redirect/%d",
1076 kRedirectCodes[r % arraysize(kRedirectCodes)]);
1077 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001078 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001079 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -07001080}
1081
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001082namespace {
1083class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1084 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001085 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001086 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001087
Amin Hassani0cd9d772018-07-31 23:55:43 -07001088 bool ReceivedBytes(HttpFetcher* fetcher,
1089 const void* bytes,
1090 size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001091 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001092 data.append(reinterpret_cast<const char*>(bytes), length);
Amin Hassani0cd9d772018-07-31 23:55:43 -07001093 return true;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001094 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001095
Alex Deymo610277e2014-11-11 21:18:11 -08001096 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001097 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001098 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001099 if (expected_response_code_ != 0)
1100 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001101 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -07001102 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001103 MessageLoop::current()->BreakLoop();
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 TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001107 ADD_FAILURE();
1108 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001109
Ben Chan02f7c1d2014-10-18 15:18:02 -07001110 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001111 int expected_response_code_;
1112 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001113};
1114
1115void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -03001116 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001117 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -07001118 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001119 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -08001120 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001121 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001122 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1123 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001124
Alex Deymo60ca1a72015-06-18 18:19:15 -07001125 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -08001126 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001127 ASSERT_TRUE(multi_fetcher);
1128 multi_fetcher->ClearRanges();
1129 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
1130 e = ranges.end(); it != e; ++it) {
1131 string tmp_str = base::StringPrintf("%jd+", it->first);
1132 if (it->second > 0) {
1133 base::StringAppendF(&tmp_str, "%jd", it->second);
1134 multi_fetcher->AddRange(it->first, it->second);
1135 } else {
1136 base::StringAppendF(&tmp_str, "?");
1137 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001138 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001139 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001140 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001141 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001142 multi_fetcher->set_delegate(&delegate);
1143
1144 MessageLoop::current()->PostTask(
1145 FROM_HERE,
1146 base::Bind(StartTransfer, multi_fetcher, url));
1147 MessageLoop::current()->Run();
1148
1149 EXPECT_EQ(expected_size, delegate.data.size());
1150 EXPECT_EQ(expected_prefix,
1151 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001152}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001153} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001154
Darin Petkov9ce452b2010-11-17 14:33:28 -08001155TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001156 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001157 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001158
Ben Chan02f7c1d2014-10-18 15:18:02 -07001159 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001160 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001161
Ben Chanf9cb98c2014-09-21 18:31:30 -07001162 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001163 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001164 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001165 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001166 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001167 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001168 ranges,
1169 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001170 kBigLength - (99 - 25),
1171 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001172}
1173
1174TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001175 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001176 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001177
Ben Chan02f7c1d2014-10-18 15:18:02 -07001178 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001179 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001180
Ben Chanf9cb98c2014-09-21 18:31:30 -07001181 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001182 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001183 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001184 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001185 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001186 ranges,
1187 "abcdefghijabcdefghijabcd",
1188 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001189 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001190}
1191
1192TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001193 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001194 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001195
Ben Chan02f7c1d2014-10-18 15:18:02 -07001196 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001197 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001198
Ben Chanf9cb98c2014-09-21 18:31:30 -07001199 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001200 ranges.push_back(make_pair(kBigLength - 2, 0));
1201 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001202 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001203 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001204 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001205 ranges,
1206 "ijhij",
1207 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001208 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001209}
1210
1211TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001212 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001213 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001214
Ben Chan02f7c1d2014-10-18 15:18:02 -07001215 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001216 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001217
Ben Chanf9cb98c2014-09-21 18:31:30 -07001218 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001219 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001220 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001221 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001222 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001223 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001224 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001225 ranges,
1226 "ij",
1227 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001228 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001229 ranges.push_back(make_pair(0, 5));
1230 }
1231}
1232
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001233// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1234// should retry with other proxies listed before giving up.
1235//
1236// (1) successful recovery: The offset fetch will fail twice but succeed with
1237// the third proxy.
1238TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1239 if (!this->test_.IsMulti())
1240 return;
1241
Ben Chan02f7c1d2014-10-18 15:18:02 -07001242 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001243 ASSERT_TRUE(server->started_);
1244
Ben Chanf9cb98c2014-09-21 18:31:30 -07001245 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001246 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001247 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001248 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001249 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001250 LocalServerUrlForPath(server->GetPort(),
1251 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001252 kBigLength)),
1253 ranges,
1254 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1255 kBigLength - (99 - 25),
1256 kHttpResponsePartialContent);
1257}
1258
1259// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1260// fetcher will signal a (failed) completed transfer to the delegate.
1261TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1262 if (!this->test_.IsMulti())
1263 return;
1264
Ben Chan02f7c1d2014-10-18 15:18:02 -07001265 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001266 ASSERT_TRUE(server->started_);
1267
Ben Chanf9cb98c2014-09-21 18:31:30 -07001268 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001269 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001270 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001271 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001272 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001273 LocalServerUrlForPath(server->GetPort(),
1274 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001275 kBigLength)),
1276 ranges,
1277 "abcdefghijabcdefghijabcde", // only received the first chunk
1278 25,
1279 kHttpResponseUndefined);
1280}
1281
Alex Deymo4ea2d922017-02-05 07:35:32 +00001282namespace {
1283// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1284class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1285 public:
1286 explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1287 : terminate_trigger_bytes_(terminate_trigger_bytes) {}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001288
Amin Hassani0cd9d772018-07-31 23:55:43 -07001289 bool ReceivedBytes(HttpFetcher* fetcher,
Alex Deymo4ea2d922017-02-05 07:35:32 +00001290 const void* bytes,
1291 size_t length) override {
1292 LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
1293 EXPECT_EQ(fetcher, fetcher_.get());
1294 if (bytes_downloaded_ < terminate_trigger_bytes_ &&
1295 bytes_downloaded_ + length >= terminate_trigger_bytes_) {
1296 MessageLoop::current()->PostTask(
1297 FROM_HERE,
1298 base::Bind(&HttpFetcher::TerminateTransfer,
1299 base::Unretained(fetcher_.get())));
1300 }
1301 bytes_downloaded_ += length;
Amin Hassani0cd9d772018-07-31 23:55:43 -07001302 return true;
Alex Deymo4ea2d922017-02-05 07:35:32 +00001303 }
1304
1305 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1306 ADD_FAILURE() << "TransferComplete called but expected a failure";
1307 // Destroy the fetcher (because we're allowed to).
1308 fetcher_.reset(nullptr);
1309 MessageLoop::current()->BreakLoop();
1310 }
1311
1312 void TransferTerminated(HttpFetcher* fetcher) override {
1313 // Destroy the fetcher (because we're allowed to).
1314 fetcher_.reset(nullptr);
1315 MessageLoop::current()->BreakLoop();
1316 }
1317
1318 unique_ptr<HttpFetcher> fetcher_;
1319 size_t bytes_downloaded_{0};
1320 size_t terminate_trigger_bytes_;
1321};
1322} // namespace
1323
1324TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
1325 if (!this->test_.IsMulti())
1326 return;
1327 const size_t kRangeTrigger = 1000;
1328 MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
1329
1330 unique_ptr<HttpServer> server(this->test_.CreateServer());
1331 ASSERT_TRUE(server->started_);
1332
1333 MultiRangeHttpFetcher* multi_fetcher =
1334 static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
1335 ASSERT_TRUE(multi_fetcher);
1336 // Transfer ownership of the fetcher to the delegate.
1337 delegate.fetcher_.reset(multi_fetcher);
1338 multi_fetcher->set_delegate(&delegate);
1339
1340 multi_fetcher->ClearRanges();
1341 multi_fetcher->AddRange(45, kRangeTrigger);
1342 multi_fetcher->AddRange(2000, 100);
1343
1344 this->test_.fake_hardware()->SetIsOfficialBuild(false);
1345
1346 StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
1347 MessageLoop::current()->Run();
1348
1349 // Check that the delegate made it to the trigger point.
1350 EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
1351}
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001352
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001353namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001354class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001355 public:
Amin Hassani0cd9d772018-07-31 23:55:43 -07001356 bool ReceivedBytes(HttpFetcher* fetcher,
1357 const void* bytes,
1358 size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001359 ADD_FAILURE();
Amin Hassani0cd9d772018-07-31 23:55:43 -07001360 return true;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001361 }
Alex Deymo610277e2014-11-11 21:18:11 -08001362 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001363 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001364 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001365 }
Alex Deymo610277e2014-11-11 21:18:11 -08001366 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001367 ADD_FAILURE();
1368 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001369};
1370
Alex Deymo60ca1a72015-06-18 18:19:15 -07001371void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1372 bool is_official_build) {
1373 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1374 return;
1375
1376 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1377 ASSERT_TRUE(server->started_);
1378
1379 BlockedTransferTestDelegate delegate;
1380 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1381 LOG(INFO) << "is_official_build: " << is_official_build;
1382 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001383 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001384 fetcher->set_delegate(&delegate);
1385
1386 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1387 StartTransfer,
1388 fetcher.get(),
1389 LocalServerUrlForPath(server->GetPort(),
1390 fetcher_test->SmallUrl(server->GetPort()))));
1391 MessageLoop::current()->Run();
1392}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001393} // namespace
1394
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001395TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001396 BlockedTransferTestHelper(&this->test_, false);
1397}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001398
Alex Deymo60ca1a72015-06-18 18:19:15 -07001399TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1400 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001401}
1402
rspangler@google.com49fdf182009-10-10 00:57:34 +00001403} // namespace chromeos_update_engine