blob: 5577b961e35d045a6481823dd9fb3cea1e349240 [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 Deymo39910dc2015-11-09 17:04:30 -080045#include "update_engine/common/http_common.h"
46#include "update_engine/common/libcurl_http_fetcher.h"
47#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 Deymof2858572016-02-25 11:20:13 -080051#include "update_engine/mock_proxy_resolver.h"
Andrew de los Reyes45168102010-11-22 11:13:50 -080052#include "update_engine/proxy_resolver.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000053
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070054using brillo::MessageLoop;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070055using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080056using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000057using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070058using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000059using std::vector;
Alex Deymof2858572016-02-25 11:20:13 -080060using testing::DoAll;
61using testing::Return;
62using testing::SaveArg;
63using testing::_;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000064
Gilad Arnold9bedeb52011-11-17 16:19:57 -080065namespace {
66
67const int kBigLength = 100000;
68const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080069const int kFlakyTruncateLength = 29000;
70const int kFlakySleepEvery = 3;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080071const int kFlakySleepSecs = 10;
72
73} // namespace
74
rspangler@google.com49fdf182009-10-10 00:57:34 +000075namespace chromeos_update_engine {
76
Gilad Arnold9bedeb52011-11-17 16:19:57 -080077static const char *kUnusedUrl = "unused://unused";
78
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070079static inline string LocalServerUrlForPath(in_port_t port,
80 const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070081 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070082 return base::StringPrintf("http://127.0.0.1%s%s", port_str.c_str(),
83 path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000084}
85
Gilad Arnold9bedeb52011-11-17 16:19:57 -080086//
87// Class hierarchy for HTTP server implementations.
88//
89
90class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000091 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080092 // This makes it an abstract class (dirty but works).
93 virtual ~HttpServer() = 0;
94
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070095 virtual in_port_t GetPort() const {
96 return 0;
97 }
98
rspangler@google.com49fdf182009-10-10 00:57:34 +000099 bool started_;
100};
101
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800102HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000103
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800104
105class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000106 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800107 NullHttpServer() {
108 started_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000109 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000110};
111
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800112
113class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000114 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700115 PythonHttpServer() : port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000116 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700117
118 // Spawn the server process.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700119 unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
Sen Jiang260f03b2016-03-21 15:34:58 -0700120 http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
Alex Deymo535f3b72015-08-07 10:51:32 -0700121 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
122
123 if (!http_server->Start()) {
124 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000125 return;
126 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700127 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700128
129 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700130 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700131 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
132 if (!stdout)
133 return;
134
135 vector<char> buf(128);
136 string line;
137 while (line.find('\n') == string::npos) {
138 size_t read;
139 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
140 ADD_FAILURE() << "error reading http server stdout";
141 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700142 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700143 line.append(buf.data(), read);
144 if (read == 0)
145 break;
146 }
147 // Parse the port from the output line.
148 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
149 if (line.size() < listening_msg_prefix_len) {
150 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700151 return;
152 }
153
Alex Deymo535f3b72015-08-07 10:51:32 -0700154 EXPECT_EQ(kServerListeningMsgPrefix,
155 line.substr(0, listening_msg_prefix_len));
156 string port_str = line.substr(listening_msg_prefix_len);
157 port_str.resize(port_str.find('\n'));
158 EXPECT_TRUE(base::StringToUint(port_str, &port_));
159
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700160 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700161 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700162
163 // Any failure before this point will SIGKILL the test server if started
164 // when the |http_server| goes out of scope.
165 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000166 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800167
rspangler@google.com49fdf182009-10-10 00:57:34 +0000168 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700169 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700170 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000171 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700172 // Wait up to 10 seconds for the process to finish. Destroying the process
173 // will kill it with a SIGKILL otherwise.
174 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000175 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800176
Alex Deymo610277e2014-11-11 21:18:11 -0800177 in_port_t GetPort() const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700178 return port_;
179 }
180
181 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700182 static const char* kServerListeningMsgPrefix;
183
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700184 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700185 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000186};
187
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700188const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
189
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800190//
191// Class hierarchy for HTTP fetcher test wrappers.
192//
193
194class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000195 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700196 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700197 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700198
Alex Deymof2858572016-02-25 11:20:13 -0800199 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
200 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
201 proxy_resolver_.set_num_proxies(num_proxies);
202 return NewLargeFetcher(&proxy_resolver_);
203 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800204 HttpFetcher* NewLargeFetcher() {
205 return NewLargeFetcher(1);
206 }
207
Alex Deymof2858572016-02-25 11:20:13 -0800208 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800209 HttpFetcher* NewSmallFetcher() {
Alex Deymof2858572016-02-25 11:20:13 -0800210 proxy_resolver_.set_num_proxies(1);
211 return NewSmallFetcher(&proxy_resolver_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800212 }
213
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700214 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
215 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
216 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800217
218 virtual bool IsMock() const = 0;
219 virtual bool IsMulti() const = 0;
220
221 virtual void IgnoreServerAborting(HttpServer* server) const {}
222
Alex Deymo60ca1a72015-06-18 18:19:15 -0700223 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800224
Alex Deymoc1c17b42015-11-23 03:53:15 -0300225 FakeHardware* fake_hardware() {
Alex Deymo706a5ab2015-11-23 17:48:30 -0300226 return &fake_hardware_;
Alex Deymoc1c17b42015-11-23 03:53:15 -0300227 }
228
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800229 protected:
230 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300231 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800232};
233
234class MockHttpFetcherTest : public AnyHttpFetcherTest {
235 public:
236 // Necessary to unhide the definition in the base class.
237 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800238 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700239 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800240 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800241 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800242 }
243
244 // Necessary to unhide the definition in the base class.
245 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800246 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
247 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800248 }
249
Alex Deymo610277e2014-11-11 21:18:11 -0800250 bool IsMock() const override { return true; }
251 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800252
Alex Deymo60ca1a72015-06-18 18:19:15 -0700253 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800254 return new NullHttpServer;
255 }
256};
257
258class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
259 public:
260 // Necessary to unhide the definition in the base class.
261 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800262 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
263 LibcurlHttpFetcher* ret =
264 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700265 // Speed up test execution.
266 ret->set_idle_seconds(1);
267 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300268 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000269 return ret;
270 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800271
272 // Necessary to unhide the definition in the base class.
273 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800274 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
275 return NewLargeFetcher(proxy_resolver);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000276 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800277
Alex Deymo610277e2014-11-11 21:18:11 -0800278 string BigUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700279 return LocalServerUrlForPath(port,
280 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800281 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000282 }
Alex Deymo610277e2014-11-11 21:18:11 -0800283 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700284 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000285 }
Alex Deymo610277e2014-11-11 21:18:11 -0800286 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700287 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800288 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800289
Alex Deymo610277e2014-11-11 21:18:11 -0800290 bool IsMock() const override { return false; }
291 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800292
Alex Deymo610277e2014-11-11 21:18:11 -0800293 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700294 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700295 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800296
Alex Deymo60ca1a72015-06-18 18:19:15 -0700297 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800298 return new PythonHttpServer;
299 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000300};
301
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800302class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700303 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800304 // Necessary to unhide the definition in the base class.
305 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800306 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
307 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
308 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800309 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800310 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700311 // Speed up test execution.
312 ret->set_idle_seconds(1);
313 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300314 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700315 return ret;
316 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800317
318 // Necessary to unhide the definition in the base class.
319 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800320 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
321 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800322 }
323
Alex Deymo610277e2014-11-11 21:18:11 -0800324 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700325};
326
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800327
328//
329// Infrastructure for type tests of HTTP fetcher.
330// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
331//
332
333// Fixture class template. We use an explicit constraint to guarantee that it
334// can only be instantiated with an AnyHttpFetcherTest type, see:
335// http://www2.research.att.com/~bs/bs_faq2.html#constraints
336template <typename T>
337class HttpFetcherTest : public ::testing::Test {
338 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700339 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700340 brillo::BaseMessageLoop loop_{&base_loop_};
Alex Deymo60ca1a72015-06-18 18:19:15 -0700341
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800342 T test_;
343
Alex Deymo60ca1a72015-06-18 18:19:15 -0700344 protected:
345 HttpFetcherTest() {
346 loop_.SetAsCurrent();
347 }
348
349 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700350 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700351 }
352
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800353 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700354 static void TypeConstraint(T* a) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800355 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700356 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700357 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800358 }
359};
360
361// Test case types list.
362typedef ::testing::Types<LibcurlHttpFetcherTest,
363 MockHttpFetcherTest,
364 MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000365TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
366
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800367
rspangler@google.com49fdf182009-10-10 00:57:34 +0000368namespace {
369class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000370 public:
Alex Deymofdd6dec2016-03-03 22:35:43 -0800371 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800372
Alex Deymo610277e2014-11-11 21:18:11 -0800373 void ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymofdd6dec2016-03-03 22:35:43 -0800374 const void* bytes,
375 size_t length) override {
376 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800377 // Update counters
378 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000379 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800380
Alex Deymo610277e2014-11-11 21:18:11 -0800381 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800382 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800383 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800384 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800385 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700386 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800387
388 // Update counter
389 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000390 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800391
Alex Deymo610277e2014-11-11 21:18:11 -0800392 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800393 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800394 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800395 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800396
Gilad Arnold48085ba2011-11-16 09:36:08 -0800397 // Are we expecting an error response? (default: no)
Alex Deymofdd6dec2016-03-03 22:35:43 -0800398 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800399
400 // Counters for callback invocations.
Alex Deymofdd6dec2016-03-03 22:35:43 -0800401 int times_transfer_complete_called_{0};
402 int times_transfer_terminated_called_{0};
403 int times_received_bytes_called_{0};
404
405 // The received data bytes.
406 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000407};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000408
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000409
Alex Deymo60ca1a72015-06-18 18:19:15 -0700410void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
411 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000412}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700413} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000414
415TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700416 HttpFetcherTestDelegate delegate;
417 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
418 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000419
Alex Deymo60ca1a72015-06-18 18:19:15 -0700420 unique_ptr<HttpServer> server(this->test_.CreateServer());
421 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000422
Alex Deymo60ca1a72015-06-18 18:19:15 -0700423 this->loop_.PostTask(FROM_HERE, base::Bind(
424 StartTransfer,
425 fetcher.get(),
426 this->test_.SmallUrl(server->GetPort())));
427 this->loop_.Run();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000428}
429
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700430TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700431 HttpFetcherTestDelegate delegate;
432 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
433 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700434
Alex Deymo60ca1a72015-06-18 18:19:15 -0700435 unique_ptr<HttpServer> server(this->test_.CreateServer());
436 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700437
Alex Deymo60ca1a72015-06-18 18:19:15 -0700438 this->loop_.PostTask(FROM_HERE, base::Bind(
439 StartTransfer,
440 fetcher.get(),
441 this->test_.BigUrl(server->GetPort())));
442 this->loop_.Run();
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700443}
444
Gilad Arnold48085ba2011-11-16 09:36:08 -0800445// Issue #9648: when server returns an error HTTP response, the fetcher needs to
446// terminate transfer prematurely, rather than try to process the error payload.
447TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800448 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800449 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700450 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800451
Alex Deymo60ca1a72015-06-18 18:19:15 -0700452 // Delegate should expect an error response.
453 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800454
Alex Deymo60ca1a72015-06-18 18:19:15 -0700455 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
456 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800457
Alex Deymo60ca1a72015-06-18 18:19:15 -0700458 unique_ptr<HttpServer> server(this->test_.CreateServer());
459 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800460
Alex Deymo60ca1a72015-06-18 18:19:15 -0700461 this->loop_.PostTask(FROM_HERE, base::Bind(
462 StartTransfer,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800463 fetcher.get(),
Alex Deymo60ca1a72015-06-18 18:19:15 -0700464 this->test_.ErrorUrl(server->GetPort())));
465 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800466
Alex Deymo60ca1a72015-06-18 18:19:15 -0700467 // Make sure that no bytes were received.
468 CHECK_EQ(delegate.times_received_bytes_called_, 0);
469 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800470
Alex Deymo60ca1a72015-06-18 18:19:15 -0700471 // Make sure that transfer completion was signaled once, and no termination
472 // was signaled.
473 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
474 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800475}
476
Alex Deymofdd6dec2016-03-03 22:35:43 -0800477TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
478 if (this->test_.IsMock())
479 return;
480
481 HttpFetcherTestDelegate delegate;
482 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
483 fetcher->set_delegate(&delegate);
484 fetcher->SetHeader("User-Agent", "MyTest");
485 fetcher->SetHeader("user-agent", "Override that header");
486 fetcher->SetHeader("Authorization", "Basic user:passwd");
487
488 // Invalid headers.
489 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
490 fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
491
492 // Hide Accept header normally added by default.
493 fetcher->SetHeader("Accept", "");
494
495 PythonHttpServer server;
496 int port = server.GetPort();
497 ASSERT_TRUE(server.started_);
498
499 StartTransfer(fetcher.get(), LocalServerUrlForPath(port, "/echo-headers"));
500 this->loop_.Run();
501
502 EXPECT_NE(string::npos,
503 delegate.data.find("user-agent: Override that header\r\n"));
504 EXPECT_NE(string::npos,
505 delegate.data.find("Authorization: Basic user:passwd\r\n"));
506
507 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
508 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
509 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
510}
511
rspangler@google.com49fdf182009-10-10 00:57:34 +0000512namespace {
513class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
514 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800515 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800516 const void* /* bytes */, size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000517 CHECK(!paused_);
518 paused_ = true;
519 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000520 }
Alex Deymo610277e2014-11-11 21:18:11 -0800521 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700522 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000523 }
Alex Deymo610277e2014-11-11 21:18:11 -0800524 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800525 ADD_FAILURE();
526 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000527 void Unpause() {
528 CHECK(paused_);
529 paused_ = false;
530 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000531 }
532 bool paused_;
533 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000534};
535
Alex Deymo60ca1a72015-06-18 18:19:15 -0700536void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
537 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000538 if (delegate->paused_)
539 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700540 // Update the task id with the new scheduled callback.
541 *my_id = MessageLoop::current()->PostDelayedTask(
542 FROM_HERE,
543 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
544 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000545}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700546} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000547
548TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800549 PausingHttpFetcherTestDelegate delegate;
550 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
551 delegate.paused_ = false;
552 delegate.fetcher_ = fetcher.get();
553 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000554
Alex Deymof2858572016-02-25 11:20:13 -0800555 unique_ptr<HttpServer> server(this->test_.CreateServer());
556 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800557
Alex Deymof2858572016-02-25 11:20:13 -0800558 MessageLoop::TaskId callback_id;
559 callback_id = this->loop_.PostDelayedTask(
560 FROM_HERE,
561 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
562 base::TimeDelta::FromMilliseconds(200));
563 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000564
Alex Deymof2858572016-02-25 11:20:13 -0800565 this->loop_.Run();
566 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
567}
568
569// This test will pause the fetcher while the download is not yet started
570// because it is waiting for the proxy to be resolved.
571TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
572 if (this->test_.IsMock())
573 return;
574 MockProxyResolver mock_resolver;
575 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
576
577 // Saved arguments from the proxy call.
Alex Deymoc00ec562017-02-05 04:36:02 +0000578 ProxiesResolvedFn proxy_callback;
579 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _))
580 .WillOnce(DoAll(SaveArg<1>(&proxy_callback), Return(true)));
Alex Deymof2858572016-02-25 11:20:13 -0800581 fetcher->BeginTransfer("http://fake_url");
582 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
583
584 // Pausing and unpausing while resolving the proxy should not affect anything.
585 fetcher->Pause();
586 fetcher->Unpause();
587 fetcher->Pause();
588 // Proxy resolver comes back after we paused the fetcher.
Alex Deymoc00ec562017-02-05 04:36:02 +0000589 ASSERT_FALSE(proxy_callback.is_null());
590 proxy_callback.Run({1, kNoProxy});
rspangler@google.com49fdf182009-10-10 00:57:34 +0000591}
592
593namespace {
594class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
595 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800596 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800597 const void* bytes, size_t length) override {}
Alex Deymo610277e2014-11-11 21:18:11 -0800598 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800599 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700600 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000601 }
Alex Deymo610277e2014-11-11 21:18:11 -0800602 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800603 EXPECT_EQ(fetcher, fetcher_.get());
604 EXPECT_FALSE(once_);
605 EXPECT_TRUE(callback_once_);
606 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700607 // The fetcher could have a callback scheduled on the ProxyResolver that
608 // can fire after this callback. We wait until the end of the test to
609 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800610 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000611 void TerminateTransfer() {
612 CHECK(once_);
613 once_ = false;
614 fetcher_->TerminateTransfer();
615 }
616 void EndLoop() {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700617 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000618 }
619 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800620 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700621 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000622};
623
Alex Deymo60ca1a72015-06-18 18:19:15 -0700624void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
625 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000626 if (delegate->once_) {
627 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700628 *my_id = MessageLoop::current()->PostTask(
629 FROM_HERE,
630 base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000631 } else {
632 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700633 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000634 }
635}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700636} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000637
638TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700639 AbortingHttpFetcherTestDelegate delegate;
640 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
641 delegate.once_ = true;
642 delegate.callback_once_ = true;
643 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000644
Alex Deymo60ca1a72015-06-18 18:19:15 -0700645 unique_ptr<HttpServer> server(this->test_.CreateServer());
646 this->test_.IgnoreServerAborting(server.get());
647 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800648
Alex Deymo60ca1a72015-06-18 18:19:15 -0700649 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000650
Alex Deymo60ca1a72015-06-18 18:19:15 -0700651 task_id = this->loop_.PostTask(
652 FROM_HERE,
653 base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
654 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
655
656 this->loop_.Run();
657 CHECK(!delegate.once_);
658 CHECK(!delegate.callback_once_);
659 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000660}
661
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000662namespace {
663class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
664 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800665 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800666 const void* bytes, size_t length) override {
667 data.append(reinterpret_cast<const char*>(bytes), length);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000668 }
Alex Deymo610277e2014-11-11 21:18:11 -0800669 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700670 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800671 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700672 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000673 }
Alex Deymo610277e2014-11-11 21:18:11 -0800674 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800675 ADD_FAILURE();
676 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000677 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000678};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700679} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000680
681TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800682 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000683 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000684 {
685 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700686 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000687 fetcher->set_delegate(&delegate);
688
Ben Chan02f7c1d2014-10-18 15:18:02 -0700689 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800690 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000691
Alex Deymo60ca1a72015-06-18 18:19:15 -0700692 this->loop_.PostTask(FROM_HERE, base::Bind(
693 &StartTransfer,
694 fetcher.get(),
695 LocalServerUrlForPath(server->GetPort(),
696 base::StringPrintf("/flaky/%d/%d/%d/%d",
697 kBigLength,
698 kFlakyTruncateLength,
699 kFlakySleepEvery,
700 kFlakySleepSecs))));
701 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000702
703 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800704 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800705 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000706 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
707 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
708 }
709 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000710}
711
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700712namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700713// This delegate kills the server attached to it after receiving any bytes.
714// This can be used for testing what happens when you try to fetch data and
715// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700716class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
717 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700718 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700719 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700720
Alex Deymo610277e2014-11-11 21:18:11 -0800721 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700722 if (server_) {
723 LOG(INFO) << "Stopping server in destructor";
724 delete server_;
725 LOG(INFO) << "server stopped";
726 }
727 }
728
Alex Deymo610277e2014-11-11 21:18:11 -0800729 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800730 const void* bytes, size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700731 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700732 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700733 delete server_;
734 LOG(INFO) << "server stopped";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700735 server_ = nullptr;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700736 }
737 }
Alex Deymo610277e2014-11-11 21:18:11 -0800738 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700739 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700740 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700741 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700742 }
Alex Deymo610277e2014-11-11 21:18:11 -0800743 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800744 ADD_FAILURE();
745 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700746 PythonHttpServer* server_;
747};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700748} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700749
750
751TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700752 // This test ensures that a fetcher responds correctly when a server isn't
753 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800754 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700755 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700756 {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700757 FailureHttpFetcherTestDelegate delegate(nullptr);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700758 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700759 fetcher->set_delegate(&delegate);
760
Alex Deymo60ca1a72015-06-18 18:19:15 -0700761 this->loop_.PostTask(FROM_HERE,
762 base::Bind(StartTransfer,
763 fetcher.get(),
764 "http://host_doesnt_exist99999999"));
765 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700766
767 // Exiting and testing happens in the delegate
768 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700769}
770
Alex Deymof123ae22015-09-24 14:59:43 -0700771TYPED_TEST(HttpFetcherTest, NoResponseTest) {
772 // This test starts a new http server but the server doesn't respond and just
773 // closes the connection.
774 if (this->test_.IsMock())
775 return;
776
777 PythonHttpServer* server = new PythonHttpServer();
778 int port = server->GetPort();
779 ASSERT_TRUE(server->started_);
780
781 // Handles destruction and claims ownership.
782 FailureHttpFetcherTestDelegate delegate(server);
783 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
784 fetcher->set_delegate(&delegate);
785 // The server will not reply at all, so we can limit the execution time of the
786 // test by reducing the low-speed timeout to something small. The test will
787 // finish once the TimeoutCallback() triggers (every second) and the timeout
788 // expired.
789 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
790
791 this->loop_.PostTask(FROM_HERE, base::Bind(
792 StartTransfer,
793 fetcher.get(),
794 LocalServerUrlForPath(port, "/hang")));
795 this->loop_.Run();
796
797 // Check that no other callback runs in the next two seconds. That would
798 // indicate a leaked callback.
799 bool timeout = false;
800 auto callback = base::Bind([&timeout]{ timeout = true;});
801 this->loop_.PostDelayedTask(FROM_HERE, callback,
802 base::TimeDelta::FromSeconds(2));
803 EXPECT_TRUE(this->loop_.RunOnce(true));
804 EXPECT_TRUE(timeout);
805}
806
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700807TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700808 // This test starts a new http server and kills it after receiving its first
809 // set of bytes. It test whether or not our fetcher eventually gives up on
810 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800811 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700812 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700813 {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700814 PythonHttpServer* server = new PythonHttpServer();
815 int port = server->GetPort();
816 ASSERT_TRUE(server->started_);
817
818 // Handles destruction and claims ownership.
819 FailureHttpFetcherTestDelegate delegate(server);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700820 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700821 fetcher->set_delegate(&delegate);
822
Alex Deymo60ca1a72015-06-18 18:19:15 -0700823 this->loop_.PostTask(FROM_HERE, base::Bind(
824 StartTransfer,
825 fetcher.get(),
826 LocalServerUrlForPath(port,
827 base::StringPrintf("/flaky/%d/%d/%d/%d",
828 kBigLength,
829 kFlakyTruncateLength,
830 kFlakySleepEvery,
831 kFlakySleepSecs))));
832 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700833
834 // Exiting and testing happens in the delegate
835 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700836}
837
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700838namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800839const HttpResponseCode kRedirectCodes[] = {
840 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
841 kHttpResponseTempRedirect
842};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700843
844class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
845 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700846 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700847 : expected_successful_(expected_successful) {}
Alex Deymo610277e2014-11-11 21:18:11 -0800848 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800849 const void* bytes, size_t length) override {
850 data.append(reinterpret_cast<const char*>(bytes), length);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700851 }
Alex Deymo610277e2014-11-11 21:18:11 -0800852 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700853 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700854 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800855 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700856 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800857 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
858 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700859 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700860 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700861 }
Alex Deymo610277e2014-11-11 21:18:11 -0800862 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800863 ADD_FAILURE();
864 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700865 bool expected_successful_;
866 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700867};
868
869// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700870void RedirectTest(const HttpServer* server,
871 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700872 const string& url,
873 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700874 RedirectHttpFetcherTestDelegate delegate(expected_successful);
875 unique_ptr<HttpFetcher> fetcher(http_fetcher);
876 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700877
Alex Deymo60ca1a72015-06-18 18:19:15 -0700878 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
879 StartTransfer,
880 fetcher.get(),
881 LocalServerUrlForPath(server->GetPort(), url)));
882 MessageLoop::current()->Run();
883 if (expected_successful) {
884 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800885 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700886 for (int i = 0; i < kMediumLength; i += 10) {
887 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
888 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700889 }
890 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700891}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700892} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700893
894TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800895 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700896 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800897
Ben Chan02f7c1d2014-10-18 15:18:02 -0700898 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800899 ASSERT_TRUE(server->started_);
900
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700901 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800902 const string url = base::StringPrintf("/redirect/%d/download/%d",
903 kRedirectCodes[c],
904 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700905 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700906 }
907}
908
909TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800910 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700911 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800912
Ben Chan02f7c1d2014-10-18 15:18:02 -0700913 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800914 ASSERT_TRUE(server->started_);
915
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700916 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700917 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700918 url += base::StringPrintf("/redirect/%d",
919 kRedirectCodes[r % arraysize(kRedirectCodes)]);
920 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800921 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700922 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700923}
924
925TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800926 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700927 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800928
Ben Chan02f7c1d2014-10-18 15:18:02 -0700929 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800930 ASSERT_TRUE(server->started_);
931
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700932 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700933 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700934 url += base::StringPrintf("/redirect/%d",
935 kRedirectCodes[r % arraysize(kRedirectCodes)]);
936 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800937 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700938 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700939}
940
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700941namespace {
942class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
943 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700944 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700945 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800946
Alex Deymo610277e2014-11-11 21:18:11 -0800947 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800948 const void* bytes, size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800949 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800950 data.append(reinterpret_cast<const char*>(bytes), length);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700951 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800952
Alex Deymo610277e2014-11-11 21:18:11 -0800953 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800954 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800955 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700956 if (expected_response_code_ != 0)
957 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800958 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700959 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -0700960 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700961 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800962
Alex Deymo610277e2014-11-11 21:18:11 -0800963 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800964 ADD_FAILURE();
965 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800966
Ben Chan02f7c1d2014-10-18 15:18:02 -0700967 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700968 int expected_response_code_;
969 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700970};
971
972void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -0300973 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700974 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -0700975 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700976 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800977 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800978 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700979 MultiHttpFetcherTestDelegate delegate(expected_response_code);
980 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -0700981
Alex Deymo60ca1a72015-06-18 18:19:15 -0700982 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -0800983 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -0700984 ASSERT_TRUE(multi_fetcher);
985 multi_fetcher->ClearRanges();
986 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
987 e = ranges.end(); it != e; ++it) {
988 string tmp_str = base::StringPrintf("%jd+", it->first);
989 if (it->second > 0) {
990 base::StringAppendF(&tmp_str, "%jd", it->second);
991 multi_fetcher->AddRange(it->first, it->second);
992 } else {
993 base::StringAppendF(&tmp_str, "?");
994 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800995 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700996 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700997 }
Alex Deymoc1c17b42015-11-23 03:53:15 -0300998 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -0700999 multi_fetcher->set_delegate(&delegate);
1000
1001 MessageLoop::current()->PostTask(
1002 FROM_HERE,
1003 base::Bind(StartTransfer, multi_fetcher, url));
1004 MessageLoop::current()->Run();
1005
1006 EXPECT_EQ(expected_size, delegate.data.size());
1007 EXPECT_EQ(expected_prefix,
1008 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001009}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001010} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001011
Darin Petkov9ce452b2010-11-17 14:33:28 -08001012TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001013 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001014 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001015
Ben Chan02f7c1d2014-10-18 15:18:02 -07001016 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001017 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001018
Ben Chanf9cb98c2014-09-21 18:31:30 -07001019 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001020 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001021 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001022 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001023 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001024 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001025 ranges,
1026 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001027 kBigLength - (99 - 25),
1028 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001029}
1030
1031TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001032 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001033 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001034
Ben Chan02f7c1d2014-10-18 15:18:02 -07001035 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001036 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001037
Ben Chanf9cb98c2014-09-21 18:31:30 -07001038 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001039 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001040 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001041 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001042 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001043 ranges,
1044 "abcdefghijabcdefghijabcd",
1045 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001046 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001047}
1048
1049TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001050 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001051 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001052
Ben Chan02f7c1d2014-10-18 15:18:02 -07001053 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001054 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001055
Ben Chanf9cb98c2014-09-21 18:31:30 -07001056 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001057 ranges.push_back(make_pair(kBigLength - 2, 0));
1058 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001059 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001060 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001061 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001062 ranges,
1063 "ijhij",
1064 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001065 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001066}
1067
1068TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001069 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001070 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001071
Ben Chan02f7c1d2014-10-18 15:18:02 -07001072 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001073 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001074
Ben Chanf9cb98c2014-09-21 18:31:30 -07001075 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001076 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001077 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001078 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001079 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001080 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001081 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001082 ranges,
1083 "ij",
1084 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001085 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001086 ranges.push_back(make_pair(0, 5));
1087 }
1088}
1089
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001090// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1091// should retry with other proxies listed before giving up.
1092//
1093// (1) successful recovery: The offset fetch will fail twice but succeed with
1094// the third proxy.
1095TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1096 if (!this->test_.IsMulti())
1097 return;
1098
Ben Chan02f7c1d2014-10-18 15:18:02 -07001099 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001100 ASSERT_TRUE(server->started_);
1101
Ben Chanf9cb98c2014-09-21 18:31:30 -07001102 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001103 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001104 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001105 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001106 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001107 LocalServerUrlForPath(server->GetPort(),
1108 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001109 kBigLength)),
1110 ranges,
1111 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1112 kBigLength - (99 - 25),
1113 kHttpResponsePartialContent);
1114}
1115
1116// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1117// fetcher will signal a (failed) completed transfer to the delegate.
1118TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1119 if (!this->test_.IsMulti())
1120 return;
1121
Ben Chan02f7c1d2014-10-18 15:18:02 -07001122 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001123 ASSERT_TRUE(server->started_);
1124
Ben Chanf9cb98c2014-09-21 18:31:30 -07001125 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001126 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001127 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001128 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001129 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001130 LocalServerUrlForPath(server->GetPort(),
1131 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001132 kBigLength)),
1133 ranges,
1134 "abcdefghijabcdefghijabcde", // only received the first chunk
1135 25,
1136 kHttpResponseUndefined);
1137}
1138
1139
1140
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001141namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001142class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001143 public:
Alex Deymo610277e2014-11-11 21:18:11 -08001144 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001145 const void* bytes, size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001146 ADD_FAILURE();
1147 }
Alex Deymo610277e2014-11-11 21:18:11 -08001148 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001149 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001150 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001151 }
Alex Deymo610277e2014-11-11 21:18:11 -08001152 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001153 ADD_FAILURE();
1154 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001155};
1156
Alex Deymo60ca1a72015-06-18 18:19:15 -07001157void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1158 bool is_official_build) {
1159 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1160 return;
1161
1162 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1163 ASSERT_TRUE(server->started_);
1164
1165 BlockedTransferTestDelegate delegate;
1166 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1167 LOG(INFO) << "is_official_build: " << is_official_build;
1168 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001169 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001170 fetcher->set_delegate(&delegate);
1171
1172 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1173 StartTransfer,
1174 fetcher.get(),
1175 LocalServerUrlForPath(server->GetPort(),
1176 fetcher_test->SmallUrl(server->GetPort()))));
1177 MessageLoop::current()->Run();
1178}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001179} // namespace
1180
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001181TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001182 BlockedTransferTestHelper(&this->test_, false);
1183}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001184
Alex Deymo60ca1a72015-06-18 18:19:15 -07001185TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1186 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001187}
1188
rspangler@google.com49fdf182009-10-10 00:57:34 +00001189} // namespace chromeos_update_engine