blob: f99007f7ace6a014d361678564495feb45099610 [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>
Alex Deymo706a5ab2015-11-23 17:48:30 -030035#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 Deymo6e3ffe72016-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 Deymo8b01f442016-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());
Alex Deymo535f3b72015-08-07 10:51:32 -0700121 base::FilePath test_server_path =
122 test_utils::GetBuildArtifactsPath().Append("test_http_server");
123 http_server->AddArg(test_server_path.value());
124 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
125
126 if (!http_server->Start()) {
127 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000128 return;
129 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700130 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700131
132 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700133 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700134 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
135 if (!stdout)
136 return;
137
138 vector<char> buf(128);
139 string line;
140 while (line.find('\n') == string::npos) {
141 size_t read;
142 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
143 ADD_FAILURE() << "error reading http server stdout";
144 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700145 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700146 line.append(buf.data(), read);
147 if (read == 0)
148 break;
149 }
150 // Parse the port from the output line.
151 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
152 if (line.size() < listening_msg_prefix_len) {
153 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700154 return;
155 }
156
Alex Deymo535f3b72015-08-07 10:51:32 -0700157 EXPECT_EQ(kServerListeningMsgPrefix,
158 line.substr(0, listening_msg_prefix_len));
159 string port_str = line.substr(listening_msg_prefix_len);
160 port_str.resize(port_str.find('\n'));
161 EXPECT_TRUE(base::StringToUint(port_str, &port_));
162
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700163 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700164 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700165
166 // Any failure before this point will SIGKILL the test server if started
167 // when the |http_server| goes out of scope.
168 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000169 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800170
rspangler@google.com49fdf182009-10-10 00:57:34 +0000171 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700172 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700173 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000174 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700175 // Wait up to 10 seconds for the process to finish. Destroying the process
176 // will kill it with a SIGKILL otherwise.
177 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000178 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800179
Alex Deymo610277e2014-11-11 21:18:11 -0800180 in_port_t GetPort() const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700181 return port_;
182 }
183
184 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700185 static const char* kServerListeningMsgPrefix;
186
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700187 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700188 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000189};
190
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700191const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
192
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800193//
194// Class hierarchy for HTTP fetcher test wrappers.
195//
196
197class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000198 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700199 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700200 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700201
Alex Deymof2858572016-02-25 11:20:13 -0800202 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
203 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
204 proxy_resolver_.set_num_proxies(num_proxies);
205 return NewLargeFetcher(&proxy_resolver_);
206 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800207 HttpFetcher* NewLargeFetcher() {
208 return NewLargeFetcher(1);
209 }
210
Alex Deymof2858572016-02-25 11:20:13 -0800211 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800212 HttpFetcher* NewSmallFetcher() {
Alex Deymof2858572016-02-25 11:20:13 -0800213 proxy_resolver_.set_num_proxies(1);
214 return NewSmallFetcher(&proxy_resolver_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800215 }
216
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700217 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
218 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
219 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800220
221 virtual bool IsMock() const = 0;
222 virtual bool IsMulti() const = 0;
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700223 virtual bool IsHttpSupported() const = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800224
225 virtual void IgnoreServerAborting(HttpServer* server) const {}
226
Alex Deymo60ca1a72015-06-18 18:19:15 -0700227 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800228
Alex Deymoc1c17b42015-11-23 03:53:15 -0300229 FakeHardware* fake_hardware() {
Alex Deymo706a5ab2015-11-23 17:48:30 -0300230 return &fake_hardware_;
Alex Deymoc1c17b42015-11-23 03:53:15 -0300231 }
232
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800233 protected:
234 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300235 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800236};
237
238class MockHttpFetcherTest : public AnyHttpFetcherTest {
239 public:
240 // Necessary to unhide the definition in the base class.
241 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800242 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700243 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800244 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800245 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800246 }
247
248 // Necessary to unhide the definition in the base class.
249 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800250 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
251 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800252 }
253
Alex Deymo610277e2014-11-11 21:18:11 -0800254 bool IsMock() const override { return true; }
255 bool IsMulti() const override { return false; }
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700256 bool IsHttpSupported() const override { return true; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800257
Alex Deymo60ca1a72015-06-18 18:19:15 -0700258 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800259 return new NullHttpServer;
260 }
261};
262
263class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
264 public:
265 // Necessary to unhide the definition in the base class.
266 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800267 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
268 LibcurlHttpFetcher* ret =
269 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700270 // Speed up test execution.
271 ret->set_idle_seconds(1);
272 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300273 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000274 return ret;
275 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800276
277 // Necessary to unhide the definition in the base class.
278 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800279 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
280 return NewLargeFetcher(proxy_resolver);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000281 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800282
Alex Deymo610277e2014-11-11 21:18:11 -0800283 string BigUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700284 return LocalServerUrlForPath(port,
285 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800286 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000287 }
Alex Deymo610277e2014-11-11 21:18:11 -0800288 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700289 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000290 }
Alex Deymo610277e2014-11-11 21:18:11 -0800291 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700292 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800293 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800294
Alex Deymo610277e2014-11-11 21:18:11 -0800295 bool IsMock() const override { return false; }
296 bool IsMulti() const override { return false; }
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700297 bool IsHttpSupported() const override { return true; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800298
Alex Deymo610277e2014-11-11 21:18:11 -0800299 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700300 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700301 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800302
Alex Deymo60ca1a72015-06-18 18:19:15 -0700303 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800304 return new PythonHttpServer;
305 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000306};
307
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800308class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700309 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800310 // Necessary to unhide the definition in the base class.
311 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800312 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
313 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
314 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800315 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800316 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700317 // Speed up test execution.
318 ret->set_idle_seconds(1);
319 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300320 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700321 return ret;
322 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800323
324 // Necessary to unhide the definition in the base class.
325 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800326 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
327 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800328 }
329
Alex Deymo610277e2014-11-11 21:18:11 -0800330 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700331};
332
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700333class FileFetcherTest : public AnyHttpFetcherTest {
334 public:
335 // Necessary to unhide the definition in the base class.
336 using AnyHttpFetcherTest::NewLargeFetcher;
337 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override {
338 return new FileFetcher();
339 }
340
341 // Necessary to unhide the definition in the base class.
342 using AnyHttpFetcherTest::NewSmallFetcher;
343 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
344 return NewLargeFetcher(proxy_resolver);
345 }
346
347 string BigUrl(in_port_t port) const override {
348 return "file://" + temp_file_.path();
349 }
350 string SmallUrl(in_port_t port) const override {
351 test_utils::WriteFileString(temp_file_.path(), "small contents");
352 return "file://" + temp_file_.path();
353 }
354 string ErrorUrl(in_port_t port) const override {
355 return "file:///path/to/non-existing-file";
356 }
357
358 bool IsMock() const override { return false; }
359 bool IsMulti() const override { return false; }
360 bool IsHttpSupported() const override { return false; }
361
362 void IgnoreServerAborting(HttpServer* server) const override {}
363
364 HttpServer* CreateServer() override { return new NullHttpServer; }
365
366 private:
367 test_utils::ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
368};
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800369
370//
371// Infrastructure for type tests of HTTP fetcher.
372// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
373//
374
375// Fixture class template. We use an explicit constraint to guarantee that it
376// can only be instantiated with an AnyHttpFetcherTest type, see:
377// http://www2.research.att.com/~bs/bs_faq2.html#constraints
378template <typename T>
379class HttpFetcherTest : public ::testing::Test {
380 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700381 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700382 brillo::BaseMessageLoop loop_{&base_loop_};
Alex Deymo60ca1a72015-06-18 18:19:15 -0700383
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800384 T test_;
385
Alex Deymo60ca1a72015-06-18 18:19:15 -0700386 protected:
387 HttpFetcherTest() {
388 loop_.SetAsCurrent();
389 }
390
391 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700392 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700393 }
394
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800395 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700396 static void TypeConstraint(T* a) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800397 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700398 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700399 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800400 }
401};
402
403// Test case types list.
404typedef ::testing::Types<LibcurlHttpFetcherTest,
405 MockHttpFetcherTest,
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700406 MultiRangeHttpFetcherTest,
407 FileFetcherTest>
408 HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000409TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
410
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800411
rspangler@google.com49fdf182009-10-10 00:57:34 +0000412namespace {
413class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000414 public:
Alex Deymo6f10c5f2016-03-03 22:35:43 -0800415 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800416
Alex Deymo610277e2014-11-11 21:18:11 -0800417 void ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymo6f10c5f2016-03-03 22:35:43 -0800418 const void* bytes,
419 size_t length) override {
420 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800421 // Update counters
422 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000423 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800424
Alex Deymo610277e2014-11-11 21:18:11 -0800425 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800426 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800427 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800428 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800429 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700430 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800431
432 // Update counter
433 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000434 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800435
Alex Deymo610277e2014-11-11 21:18:11 -0800436 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800437 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800438 times_transfer_terminated_called_++;
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700439 MessageLoop::current()->BreakLoop();
Darin Petkov9ce452b2010-11-17 14:33:28 -0800440 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800441
Gilad Arnold48085ba2011-11-16 09:36:08 -0800442 // Are we expecting an error response? (default: no)
Alex Deymo6f10c5f2016-03-03 22:35:43 -0800443 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800444
445 // Counters for callback invocations.
Alex Deymo6f10c5f2016-03-03 22:35:43 -0800446 int times_transfer_complete_called_{0};
447 int times_transfer_terminated_called_{0};
448 int times_received_bytes_called_{0};
449
450 // The received data bytes.
451 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000452};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000453
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000454
Alex Deymo60ca1a72015-06-18 18:19:15 -0700455void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
456 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000457}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700458} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000459
460TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700461 HttpFetcherTestDelegate delegate;
462 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
463 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000464
Alex Deymo60ca1a72015-06-18 18:19:15 -0700465 unique_ptr<HttpServer> server(this->test_.CreateServer());
466 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000467
Alex Deymo60ca1a72015-06-18 18:19:15 -0700468 this->loop_.PostTask(FROM_HERE, base::Bind(
469 StartTransfer,
470 fetcher.get(),
471 this->test_.SmallUrl(server->GetPort())));
472 this->loop_.Run();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000473}
474
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700475TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700476 HttpFetcherTestDelegate delegate;
477 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
478 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700479
Alex Deymo60ca1a72015-06-18 18:19:15 -0700480 unique_ptr<HttpServer> server(this->test_.CreateServer());
481 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700482
Alex Deymo60ca1a72015-06-18 18:19:15 -0700483 this->loop_.PostTask(FROM_HERE, base::Bind(
484 StartTransfer,
485 fetcher.get(),
486 this->test_.BigUrl(server->GetPort())));
487 this->loop_.Run();
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.
513 CHECK_EQ(delegate.times_received_bytes_called_, 0);
514 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
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.
518 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
519 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800520}
521
Alex Deymo6f10c5f2016-03-03 22:35:43 -0800522TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700523 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymo6f10c5f2016-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 Deymo6e3ffe72016-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 Deymo6f10c5f2016-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:
Alex Deymo610277e2014-11-11 21:18:11 -0800564 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800565 const void* /* bytes */, size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000566 CHECK(!paused_);
567 paused_ = true;
568 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000569 }
Alex Deymo610277e2014-11-11 21:18:11 -0800570 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700571 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000572 }
Alex Deymo610277e2014-11-11 21:18:11 -0800573 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800574 ADD_FAILURE();
575 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000576 void Unpause() {
577 CHECK(paused_);
578 paused_ = false;
579 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000580 }
581 bool paused_;
582 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000583};
584
Alex Deymo60ca1a72015-06-18 18:19:15 -0700585void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
586 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000587 if (delegate->paused_)
588 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700589 // Update the task id with the new scheduled callback.
590 *my_id = MessageLoop::current()->PostDelayedTask(
591 FROM_HERE,
592 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
593 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000594}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700595} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000596
597TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800598 PausingHttpFetcherTestDelegate delegate;
599 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
600 delegate.paused_ = false;
601 delegate.fetcher_ = fetcher.get();
602 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000603
Alex Deymof2858572016-02-25 11:20:13 -0800604 unique_ptr<HttpServer> server(this->test_.CreateServer());
605 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800606
Alex Deymof2858572016-02-25 11:20:13 -0800607 MessageLoop::TaskId callback_id;
608 callback_id = this->loop_.PostDelayedTask(
609 FROM_HERE,
610 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
611 base::TimeDelta::FromMilliseconds(200));
612 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000613
Alex Deymof2858572016-02-25 11:20:13 -0800614 this->loop_.Run();
615 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
616}
617
618// This test will pause the fetcher while the download is not yet started
619// because it is waiting for the proxy to be resolved.
620TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700621 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Alex Deymof2858572016-02-25 11:20:13 -0800622 return;
623 MockProxyResolver mock_resolver;
624 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
625
626 // Saved arguments from the proxy call.
627 ProxiesResolvedFn proxy_callback = nullptr;
628 void* proxy_data = nullptr;
629
630 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _, _))
631 .WillOnce(DoAll(
632 SaveArg<1>(&proxy_callback), SaveArg<2>(&proxy_data), Return(true)));
633 fetcher->BeginTransfer("http://fake_url");
634 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
635
636 // Pausing and unpausing while resolving the proxy should not affect anything.
637 fetcher->Pause();
638 fetcher->Unpause();
639 fetcher->Pause();
640 // Proxy resolver comes back after we paused the fetcher.
641 ASSERT_TRUE(proxy_callback);
642 (*proxy_callback)({1, kNoProxy}, proxy_data);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000643}
644
645namespace {
646class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
647 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800648 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800649 const void* bytes, size_t length) override {}
Alex Deymo610277e2014-11-11 21:18:11 -0800650 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800651 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700652 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000653 }
Alex Deymo610277e2014-11-11 21:18:11 -0800654 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800655 EXPECT_EQ(fetcher, fetcher_.get());
656 EXPECT_FALSE(once_);
657 EXPECT_TRUE(callback_once_);
658 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700659 // The fetcher could have a callback scheduled on the ProxyResolver that
660 // can fire after this callback. We wait until the end of the test to
661 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800662 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000663 void TerminateTransfer() {
664 CHECK(once_);
665 once_ = false;
666 fetcher_->TerminateTransfer();
667 }
668 void EndLoop() {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700669 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000670 }
671 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800672 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700673 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000674};
675
Alex Deymo60ca1a72015-06-18 18:19:15 -0700676void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
677 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000678 if (delegate->once_) {
679 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700680 *my_id = MessageLoop::current()->PostTask(
681 FROM_HERE,
682 base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000683 } else {
684 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700685 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000686 }
687}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700688} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000689
690TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700691 AbortingHttpFetcherTestDelegate delegate;
692 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
693 delegate.once_ = true;
694 delegate.callback_once_ = true;
695 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000696
Alex Deymo60ca1a72015-06-18 18:19:15 -0700697 unique_ptr<HttpServer> server(this->test_.CreateServer());
698 this->test_.IgnoreServerAborting(server.get());
699 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800700
Alex Deymo60ca1a72015-06-18 18:19:15 -0700701 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000702
Alex Deymo60ca1a72015-06-18 18:19:15 -0700703 task_id = this->loop_.PostTask(
704 FROM_HERE,
705 base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
706 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
707
708 this->loop_.Run();
709 CHECK(!delegate.once_);
710 CHECK(!delegate.callback_once_);
711 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000712}
713
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000714namespace {
715class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
716 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800717 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800718 const void* bytes, size_t length) override {
719 data.append(reinterpret_cast<const char*>(bytes), length);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000720 }
Alex Deymo610277e2014-11-11 21:18:11 -0800721 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700722 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800723 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700724 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000725 }
Alex Deymo610277e2014-11-11 21:18:11 -0800726 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800727 ADD_FAILURE();
728 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000729 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000730};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700731} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000732
733TYPED_TEST(HttpFetcherTest, FlakyTest) {
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700734 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000735 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000736 {
737 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700738 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000739 fetcher->set_delegate(&delegate);
740
Ben Chan02f7c1d2014-10-18 15:18:02 -0700741 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800742 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000743
Alex Deymo60ca1a72015-06-18 18:19:15 -0700744 this->loop_.PostTask(FROM_HERE, base::Bind(
745 &StartTransfer,
746 fetcher.get(),
747 LocalServerUrlForPath(server->GetPort(),
748 base::StringPrintf("/flaky/%d/%d/%d/%d",
749 kBigLength,
750 kFlakyTruncateLength,
751 kFlakySleepEvery,
752 kFlakySleepSecs))));
753 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000754
755 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800756 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800757 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000758 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
759 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
760 }
761 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000762}
763
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700764namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700765// This delegate kills the server attached to it after receiving any bytes.
766// This can be used for testing what happens when you try to fetch data and
767// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700768class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
769 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700770 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700771 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700772
Alex Deymo610277e2014-11-11 21:18:11 -0800773 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700774 if (server_) {
775 LOG(INFO) << "Stopping server in destructor";
776 delete server_;
777 LOG(INFO) << "server stopped";
778 }
779 }
780
Alex Deymo610277e2014-11-11 21:18:11 -0800781 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800782 const void* bytes, size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700783 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700784 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700785 delete server_;
786 LOG(INFO) << "server stopped";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700787 server_ = nullptr;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700788 }
789 }
Alex Deymo610277e2014-11-11 21:18:11 -0800790 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700791 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700792 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700793 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700794 }
Alex Deymo610277e2014-11-11 21:18:11 -0800795 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800796 ADD_FAILURE();
797 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700798 PythonHttpServer* server_;
799};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700800} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700801
802
803TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700804 // This test ensures that a fetcher responds correctly when a server isn't
805 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800806 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700807 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700808 {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700809 FailureHttpFetcherTestDelegate delegate(nullptr);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700810 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700811 fetcher->set_delegate(&delegate);
812
Alex Deymo60ca1a72015-06-18 18:19:15 -0700813 this->loop_.PostTask(FROM_HERE,
814 base::Bind(StartTransfer,
815 fetcher.get(),
816 "http://host_doesnt_exist99999999"));
817 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700818
819 // Exiting and testing happens in the delegate
820 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700821}
822
Alex Deymof123ae22015-09-24 14:59:43 -0700823TYPED_TEST(HttpFetcherTest, NoResponseTest) {
824 // This test starts a new http server but the server doesn't respond and just
825 // closes the connection.
826 if (this->test_.IsMock())
827 return;
828
829 PythonHttpServer* server = new PythonHttpServer();
830 int port = server->GetPort();
831 ASSERT_TRUE(server->started_);
832
833 // Handles destruction and claims ownership.
834 FailureHttpFetcherTestDelegate delegate(server);
835 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
836 fetcher->set_delegate(&delegate);
837 // The server will not reply at all, so we can limit the execution time of the
838 // test by reducing the low-speed timeout to something small. The test will
839 // finish once the TimeoutCallback() triggers (every second) and the timeout
840 // expired.
841 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
842
843 this->loop_.PostTask(FROM_HERE, base::Bind(
844 StartTransfer,
845 fetcher.get(),
846 LocalServerUrlForPath(port, "/hang")));
847 this->loop_.Run();
848
849 // Check that no other callback runs in the next two seconds. That would
850 // indicate a leaked callback.
851 bool timeout = false;
852 auto callback = base::Bind([&timeout]{ timeout = true;});
853 this->loop_.PostDelayedTask(FROM_HERE, callback,
854 base::TimeDelta::FromSeconds(2));
855 EXPECT_TRUE(this->loop_.RunOnce(true));
856 EXPECT_TRUE(timeout);
857}
858
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700859TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700860 // This test starts a new http server and kills it after receiving its first
861 // set of bytes. It test whether or not our fetcher eventually gives up on
862 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800863 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700864 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700865 {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700866 PythonHttpServer* server = new PythonHttpServer();
867 int port = server->GetPort();
868 ASSERT_TRUE(server->started_);
869
870 // Handles destruction and claims ownership.
871 FailureHttpFetcherTestDelegate delegate(server);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700872 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700873 fetcher->set_delegate(&delegate);
874
Alex Deymo60ca1a72015-06-18 18:19:15 -0700875 this->loop_.PostTask(FROM_HERE, base::Bind(
876 StartTransfer,
877 fetcher.get(),
878 LocalServerUrlForPath(port,
879 base::StringPrintf("/flaky/%d/%d/%d/%d",
880 kBigLength,
881 kFlakyTruncateLength,
882 kFlakySleepEvery,
883 kFlakySleepSecs))));
884 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700885
886 // Exiting and testing happens in the delegate
887 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700888}
889
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700890namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800891const HttpResponseCode kRedirectCodes[] = {
892 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
893 kHttpResponseTempRedirect
894};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700895
896class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
897 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700898 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700899 : expected_successful_(expected_successful) {}
Alex Deymo610277e2014-11-11 21:18:11 -0800900 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800901 const void* bytes, size_t length) override {
902 data.append(reinterpret_cast<const char*>(bytes), length);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700903 }
Alex Deymo610277e2014-11-11 21:18:11 -0800904 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700905 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700906 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800907 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700908 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800909 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
910 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700911 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700912 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700913 }
Alex Deymo610277e2014-11-11 21:18:11 -0800914 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800915 ADD_FAILURE();
916 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700917 bool expected_successful_;
918 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700919};
920
921// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700922void RedirectTest(const HttpServer* server,
923 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700924 const string& url,
925 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700926 RedirectHttpFetcherTestDelegate delegate(expected_successful);
927 unique_ptr<HttpFetcher> fetcher(http_fetcher);
928 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700929
Alex Deymo60ca1a72015-06-18 18:19:15 -0700930 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
931 StartTransfer,
932 fetcher.get(),
933 LocalServerUrlForPath(server->GetPort(), url)));
934 MessageLoop::current()->Run();
935 if (expected_successful) {
936 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800937 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700938 for (int i = 0; i < kMediumLength; i += 10) {
939 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
940 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700941 }
942 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700943}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700944} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700945
946TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700947 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700948 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800949
Ben Chan02f7c1d2014-10-18 15:18:02 -0700950 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800951 ASSERT_TRUE(server->started_);
952
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700953 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800954 const string url = base::StringPrintf("/redirect/%d/download/%d",
955 kRedirectCodes[c],
956 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700957 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700958 }
959}
960
961TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700962 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700963 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800964
Ben Chan02f7c1d2014-10-18 15:18:02 -0700965 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800966 ASSERT_TRUE(server->started_);
967
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700968 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700969 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700970 url += base::StringPrintf("/redirect/%d",
971 kRedirectCodes[r % arraysize(kRedirectCodes)]);
972 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800973 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700974 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700975}
976
977TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Alex Deymo6e3ffe72016-05-26 16:43:13 -0700978 if (this->test_.IsMock() || !this->test_.IsHttpSupported())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700979 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800980
Ben Chan02f7c1d2014-10-18 15:18:02 -0700981 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800982 ASSERT_TRUE(server->started_);
983
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700984 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700985 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700986 url += base::StringPrintf("/redirect/%d",
987 kRedirectCodes[r % arraysize(kRedirectCodes)]);
988 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800989 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700990 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700991}
992
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700993namespace {
994class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
995 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700996 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700997 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800998
Alex Deymo610277e2014-11-11 21:18:11 -0800999 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001000 const void* bytes, size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001001 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001002 data.append(reinterpret_cast<const char*>(bytes), length);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001003 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001004
Alex Deymo610277e2014-11-11 21:18:11 -08001005 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001006 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001007 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001008 if (expected_response_code_ != 0)
1009 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001010 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -07001011 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001012 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001013 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001014
Alex Deymo610277e2014-11-11 21:18:11 -08001015 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001016 ADD_FAILURE();
1017 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001018
Ben Chan02f7c1d2014-10-18 15:18:02 -07001019 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001020 int expected_response_code_;
1021 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001022};
1023
1024void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -03001025 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001026 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -07001027 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001028 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -08001029 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001030 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001031 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1032 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001033
Alex Deymo60ca1a72015-06-18 18:19:15 -07001034 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -08001035 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001036 ASSERT_TRUE(multi_fetcher);
1037 multi_fetcher->ClearRanges();
1038 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
1039 e = ranges.end(); it != e; ++it) {
1040 string tmp_str = base::StringPrintf("%jd+", it->first);
1041 if (it->second > 0) {
1042 base::StringAppendF(&tmp_str, "%jd", it->second);
1043 multi_fetcher->AddRange(it->first, it->second);
1044 } else {
1045 base::StringAppendF(&tmp_str, "?");
1046 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001047 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001048 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001049 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001050 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001051 multi_fetcher->set_delegate(&delegate);
1052
1053 MessageLoop::current()->PostTask(
1054 FROM_HERE,
1055 base::Bind(StartTransfer, multi_fetcher, url));
1056 MessageLoop::current()->Run();
1057
1058 EXPECT_EQ(expected_size, delegate.data.size());
1059 EXPECT_EQ(expected_prefix,
1060 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001061}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001062} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001063
Darin Petkov9ce452b2010-11-17 14:33:28 -08001064TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001065 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001066 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001067
Ben Chan02f7c1d2014-10-18 15:18:02 -07001068 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001069 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001070
Ben Chanf9cb98c2014-09-21 18:31:30 -07001071 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001072 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001073 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001074 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001075 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001076 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001077 ranges,
1078 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001079 kBigLength - (99 - 25),
1080 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001081}
1082
1083TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001084 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001085 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001086
Ben Chan02f7c1d2014-10-18 15:18:02 -07001087 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001088 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001089
Ben Chanf9cb98c2014-09-21 18:31:30 -07001090 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001091 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001092 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001093 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001094 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001095 ranges,
1096 "abcdefghijabcdefghijabcd",
1097 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001098 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001099}
1100
1101TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001102 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001103 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001104
Ben Chan02f7c1d2014-10-18 15:18:02 -07001105 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001106 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001107
Ben Chanf9cb98c2014-09-21 18:31:30 -07001108 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001109 ranges.push_back(make_pair(kBigLength - 2, 0));
1110 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001111 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001112 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001113 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001114 ranges,
1115 "ijhij",
1116 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001117 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001118}
1119
1120TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001121 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001122 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001123
Ben Chan02f7c1d2014-10-18 15:18:02 -07001124 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001125 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001126
Ben Chanf9cb98c2014-09-21 18:31:30 -07001127 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001128 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001129 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001130 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001131 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001132 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001133 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001134 ranges,
1135 "ij",
1136 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001137 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001138 ranges.push_back(make_pair(0, 5));
1139 }
1140}
1141
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001142// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1143// should retry with other proxies listed before giving up.
1144//
1145// (1) successful recovery: The offset fetch will fail twice but succeed with
1146// the third proxy.
1147TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1148 if (!this->test_.IsMulti())
1149 return;
1150
Ben Chan02f7c1d2014-10-18 15:18:02 -07001151 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001152 ASSERT_TRUE(server->started_);
1153
Ben Chanf9cb98c2014-09-21 18:31:30 -07001154 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001155 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001156 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001157 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001158 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001159 LocalServerUrlForPath(server->GetPort(),
1160 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001161 kBigLength)),
1162 ranges,
1163 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1164 kBigLength - (99 - 25),
1165 kHttpResponsePartialContent);
1166}
1167
1168// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1169// fetcher will signal a (failed) completed transfer to the delegate.
1170TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1171 if (!this->test_.IsMulti())
1172 return;
1173
Ben Chan02f7c1d2014-10-18 15:18:02 -07001174 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001175 ASSERT_TRUE(server->started_);
1176
Ben Chanf9cb98c2014-09-21 18:31:30 -07001177 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001178 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001179 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001180 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001181 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001182 LocalServerUrlForPath(server->GetPort(),
1183 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001184 kBigLength)),
1185 ranges,
1186 "abcdefghijabcdefghijabcde", // only received the first chunk
1187 25,
1188 kHttpResponseUndefined);
1189}
1190
1191
1192
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001193namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001194class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001195 public:
Alex Deymo610277e2014-11-11 21:18:11 -08001196 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001197 const void* bytes, size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001198 ADD_FAILURE();
1199 }
Alex Deymo610277e2014-11-11 21:18:11 -08001200 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001201 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001202 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001203 }
Alex Deymo610277e2014-11-11 21:18:11 -08001204 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001205 ADD_FAILURE();
1206 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001207};
1208
Alex Deymo60ca1a72015-06-18 18:19:15 -07001209void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1210 bool is_official_build) {
1211 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1212 return;
1213
1214 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1215 ASSERT_TRUE(server->started_);
1216
1217 BlockedTransferTestDelegate delegate;
1218 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1219 LOG(INFO) << "is_official_build: " << is_official_build;
1220 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001221 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001222 fetcher->set_delegate(&delegate);
1223
1224 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1225 StartTransfer,
1226 fetcher.get(),
1227 LocalServerUrlForPath(server->GetPort(),
1228 fetcher_test->SmallUrl(server->GetPort()))));
1229 MessageLoop::current()->Run();
1230}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001231} // namespace
1232
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001233TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001234 BlockedTransferTestHelper(&this->test_, false);
1235}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001236
Alex Deymo60ca1a72015-06-18 18:19:15 -07001237TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1238 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001239}
1240
rspangler@google.com49fdf182009-10-10 00:57:34 +00001241} // namespace chromeos_update_engine