blob: 0d4b5da507e8c29f3d4c4a12a19de7e59b2d0194 [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());
Alex Deymo535f3b72015-08-07 10:51:32 -0700120 base::FilePath test_server_path =
121 test_utils::GetBuildArtifactsPath().Append("test_http_server");
122 http_server->AddArg(test_server_path.value());
123 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
124
125 if (!http_server->Start()) {
126 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000127 return;
128 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700129 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700130
131 // Wait for server to begin accepting connections, obtain its port.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700132 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
Alex Deymo535f3b72015-08-07 10:51:32 -0700133 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
134 if (!stdout)
135 return;
136
137 vector<char> buf(128);
138 string line;
139 while (line.find('\n') == string::npos) {
140 size_t read;
141 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
142 ADD_FAILURE() << "error reading http server stdout";
143 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700144 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700145 line.append(buf.data(), read);
146 if (read == 0)
147 break;
148 }
149 // Parse the port from the output line.
150 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
151 if (line.size() < listening_msg_prefix_len) {
152 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700153 return;
154 }
155
Alex Deymo535f3b72015-08-07 10:51:32 -0700156 EXPECT_EQ(kServerListeningMsgPrefix,
157 line.substr(0, listening_msg_prefix_len));
158 string port_str = line.substr(listening_msg_prefix_len);
159 port_str.resize(port_str.find('\n'));
160 EXPECT_TRUE(base::StringToUint(port_str, &port_));
161
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700162 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700163 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700164
165 // Any failure before this point will SIGKILL the test server if started
166 // when the |http_server| goes out of scope.
167 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000168 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800169
rspangler@google.com49fdf182009-10-10 00:57:34 +0000170 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700171 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700172 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000173 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700174 // Wait up to 10 seconds for the process to finish. Destroying the process
175 // will kill it with a SIGKILL otherwise.
176 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000177 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800178
Alex Deymo610277e2014-11-11 21:18:11 -0800179 in_port_t GetPort() const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700180 return port_;
181 }
182
183 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700184 static const char* kServerListeningMsgPrefix;
185
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700186 unique_ptr<brillo::Process> http_server_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700187 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000188};
189
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700190const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
191
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800192//
193// Class hierarchy for HTTP fetcher test wrappers.
194//
195
196class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000197 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700198 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700199 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700200
Alex Deymof2858572016-02-25 11:20:13 -0800201 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
202 HttpFetcher* NewLargeFetcher(size_t num_proxies) {
203 proxy_resolver_.set_num_proxies(num_proxies);
204 return NewLargeFetcher(&proxy_resolver_);
205 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800206 HttpFetcher* NewLargeFetcher() {
207 return NewLargeFetcher(1);
208 }
209
Alex Deymof2858572016-02-25 11:20:13 -0800210 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800211 HttpFetcher* NewSmallFetcher() {
Alex Deymof2858572016-02-25 11:20:13 -0800212 proxy_resolver_.set_num_proxies(1);
213 return NewSmallFetcher(&proxy_resolver_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800214 }
215
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700216 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
217 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
218 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800219
220 virtual bool IsMock() const = 0;
221 virtual bool IsMulti() const = 0;
222
223 virtual void IgnoreServerAborting(HttpServer* server) const {}
224
Alex Deymo60ca1a72015-06-18 18:19:15 -0700225 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800226
Alex Deymoc1c17b42015-11-23 03:53:15 -0300227 FakeHardware* fake_hardware() {
Alex Deymo706a5ab2015-11-23 17:48:30 -0300228 return &fake_hardware_;
Alex Deymoc1c17b42015-11-23 03:53:15 -0300229 }
230
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800231 protected:
232 DirectProxyResolver proxy_resolver_;
Alex Deymo706a5ab2015-11-23 17:48:30 -0300233 FakeHardware fake_hardware_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800234};
235
236class MockHttpFetcherTest : public AnyHttpFetcherTest {
237 public:
238 // Necessary to unhide the definition in the base class.
239 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800240 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700241 brillo::Blob big_data(1000000);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800242 return new MockHttpFetcher(
Alex Deymof2858572016-02-25 11:20:13 -0800243 big_data.data(), big_data.size(), proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800244 }
245
246 // Necessary to unhide the definition in the base class.
247 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800248 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
249 return new MockHttpFetcher("x", 1, proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800250 }
251
Alex Deymo610277e2014-11-11 21:18:11 -0800252 bool IsMock() const override { return true; }
253 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800254
Alex Deymo60ca1a72015-06-18 18:19:15 -0700255 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800256 return new NullHttpServer;
257 }
258};
259
260class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
261 public:
262 // Necessary to unhide the definition in the base class.
263 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800264 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
265 LibcurlHttpFetcher* ret =
266 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700267 // Speed up test execution.
268 ret->set_idle_seconds(1);
269 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300270 fake_hardware_.SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000271 return ret;
272 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800273
274 // Necessary to unhide the definition in the base class.
275 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800276 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
277 return NewLargeFetcher(proxy_resolver);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000278 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800279
Alex Deymo610277e2014-11-11 21:18:11 -0800280 string BigUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700281 return LocalServerUrlForPath(port,
282 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800283 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000284 }
Alex Deymo610277e2014-11-11 21:18:11 -0800285 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700286 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000287 }
Alex Deymo610277e2014-11-11 21:18:11 -0800288 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700289 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800290 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800291
Alex Deymo610277e2014-11-11 21:18:11 -0800292 bool IsMock() const override { return false; }
293 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800294
Alex Deymo610277e2014-11-11 21:18:11 -0800295 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700296 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700297 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800298
Alex Deymo60ca1a72015-06-18 18:19:15 -0700299 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800300 return new PythonHttpServer;
301 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000302};
303
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800304class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700305 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800306 // Necessary to unhide the definition in the base class.
307 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800308 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override {
309 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(
310 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800311 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800312 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700313 // Speed up test execution.
314 ret->set_idle_seconds(1);
315 ret->set_retry_seconds(1);
Alex Deymo706a5ab2015-11-23 17:48:30 -0300316 fake_hardware_.SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700317 return ret;
318 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800319
320 // Necessary to unhide the definition in the base class.
321 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymof2858572016-02-25 11:20:13 -0800322 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
323 return NewLargeFetcher(proxy_resolver);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800324 }
325
Alex Deymo610277e2014-11-11 21:18:11 -0800326 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700327};
328
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800329
330//
331// Infrastructure for type tests of HTTP fetcher.
332// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
333//
334
335// Fixture class template. We use an explicit constraint to guarantee that it
336// can only be instantiated with an AnyHttpFetcherTest type, see:
337// http://www2.research.att.com/~bs/bs_faq2.html#constraints
338template <typename T>
339class HttpFetcherTest : public ::testing::Test {
340 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700341 base::MessageLoopForIO base_loop_;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700342 brillo::BaseMessageLoop loop_{&base_loop_};
Alex Deymo60ca1a72015-06-18 18:19:15 -0700343
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800344 T test_;
345
Alex Deymo60ca1a72015-06-18 18:19:15 -0700346 protected:
347 HttpFetcherTest() {
348 loop_.SetAsCurrent();
349 }
350
351 void TearDown() override {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700352 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
Alex Deymo60ca1a72015-06-18 18:19:15 -0700353 }
354
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800355 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700356 static void TypeConstraint(T* a) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800357 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700358 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700359 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800360 }
361};
362
363// Test case types list.
364typedef ::testing::Types<LibcurlHttpFetcherTest,
365 MockHttpFetcherTest,
366 MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000367TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
368
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800369
rspangler@google.com49fdf182009-10-10 00:57:34 +0000370namespace {
371class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000372 public:
Alex Deymofdd6dec2016-03-03 22:35:43 -0800373 HttpFetcherTestDelegate() = default;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800374
Alex Deymo610277e2014-11-11 21:18:11 -0800375 void ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Deymofdd6dec2016-03-03 22:35:43 -0800376 const void* bytes,
377 size_t length) override {
378 data.append(reinterpret_cast<const char*>(bytes), length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800379 // Update counters
380 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000381 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800382
Alex Deymo610277e2014-11-11 21:18:11 -0800383 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800384 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800385 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800386 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800387 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700388 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800389
390 // Update counter
391 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000392 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800393
Alex Deymo610277e2014-11-11 21:18:11 -0800394 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800395 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800396 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800397 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800398
Gilad Arnold48085ba2011-11-16 09:36:08 -0800399 // Are we expecting an error response? (default: no)
Alex Deymofdd6dec2016-03-03 22:35:43 -0800400 bool is_expect_error_{false};
Gilad Arnold48085ba2011-11-16 09:36:08 -0800401
402 // Counters for callback invocations.
Alex Deymofdd6dec2016-03-03 22:35:43 -0800403 int times_transfer_complete_called_{0};
404 int times_transfer_terminated_called_{0};
405 int times_received_bytes_called_{0};
406
407 // The received data bytes.
408 string data;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000409};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000410
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000411
Alex Deymo60ca1a72015-06-18 18:19:15 -0700412void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
413 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000414}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700415} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000416
417TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700418 HttpFetcherTestDelegate delegate;
419 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
420 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000421
Alex Deymo60ca1a72015-06-18 18:19:15 -0700422 unique_ptr<HttpServer> server(this->test_.CreateServer());
423 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000424
Alex Deymo60ca1a72015-06-18 18:19:15 -0700425 this->loop_.PostTask(FROM_HERE, base::Bind(
426 StartTransfer,
427 fetcher.get(),
428 this->test_.SmallUrl(server->GetPort())));
429 this->loop_.Run();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000430}
431
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700432TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700433 HttpFetcherTestDelegate delegate;
434 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
435 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700436
Alex Deymo60ca1a72015-06-18 18:19:15 -0700437 unique_ptr<HttpServer> server(this->test_.CreateServer());
438 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700439
Alex Deymo60ca1a72015-06-18 18:19:15 -0700440 this->loop_.PostTask(FROM_HERE, base::Bind(
441 StartTransfer,
442 fetcher.get(),
443 this->test_.BigUrl(server->GetPort())));
444 this->loop_.Run();
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700445}
446
Gilad Arnold48085ba2011-11-16 09:36:08 -0800447// Issue #9648: when server returns an error HTTP response, the fetcher needs to
448// terminate transfer prematurely, rather than try to process the error payload.
449TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800450 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800451 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700452 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800453
Alex Deymo60ca1a72015-06-18 18:19:15 -0700454 // Delegate should expect an error response.
455 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800456
Alex Deymo60ca1a72015-06-18 18:19:15 -0700457 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
458 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800459
Alex Deymo60ca1a72015-06-18 18:19:15 -0700460 unique_ptr<HttpServer> server(this->test_.CreateServer());
461 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800462
Alex Deymo60ca1a72015-06-18 18:19:15 -0700463 this->loop_.PostTask(FROM_HERE, base::Bind(
464 StartTransfer,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800465 fetcher.get(),
Alex Deymo60ca1a72015-06-18 18:19:15 -0700466 this->test_.ErrorUrl(server->GetPort())));
467 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800468
Alex Deymo60ca1a72015-06-18 18:19:15 -0700469 // Make sure that no bytes were received.
470 CHECK_EQ(delegate.times_received_bytes_called_, 0);
471 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800472
Alex Deymo60ca1a72015-06-18 18:19:15 -0700473 // Make sure that transfer completion was signaled once, and no termination
474 // was signaled.
475 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
476 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800477}
478
Alex Deymofdd6dec2016-03-03 22:35:43 -0800479TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
480 if (this->test_.IsMock())
481 return;
482
483 HttpFetcherTestDelegate delegate;
484 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
485 fetcher->set_delegate(&delegate);
486 fetcher->SetHeader("User-Agent", "MyTest");
487 fetcher->SetHeader("user-agent", "Override that header");
488 fetcher->SetHeader("Authorization", "Basic user:passwd");
489
490 // Invalid headers.
491 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
492 fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
493
494 // Hide Accept header normally added by default.
495 fetcher->SetHeader("Accept", "");
496
497 PythonHttpServer server;
498 int port = server.GetPort();
499 ASSERT_TRUE(server.started_);
500
501 StartTransfer(fetcher.get(), LocalServerUrlForPath(port, "/echo-headers"));
502 this->loop_.Run();
503
504 EXPECT_NE(string::npos,
505 delegate.data.find("user-agent: Override that header\r\n"));
506 EXPECT_NE(string::npos,
507 delegate.data.find("Authorization: Basic user:passwd\r\n"));
508
509 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
510 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
511 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
512}
513
rspangler@google.com49fdf182009-10-10 00:57:34 +0000514namespace {
515class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
516 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800517 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800518 const void* /* bytes */, size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000519 CHECK(!paused_);
520 paused_ = true;
521 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000522 }
Alex Deymo610277e2014-11-11 21:18:11 -0800523 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700524 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000525 }
Alex Deymo610277e2014-11-11 21:18:11 -0800526 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800527 ADD_FAILURE();
528 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000529 void Unpause() {
530 CHECK(paused_);
531 paused_ = false;
532 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000533 }
534 bool paused_;
535 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000536};
537
Alex Deymo60ca1a72015-06-18 18:19:15 -0700538void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
539 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000540 if (delegate->paused_)
541 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700542 // Update the task id with the new scheduled callback.
543 *my_id = MessageLoop::current()->PostDelayedTask(
544 FROM_HERE,
545 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
546 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000547}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700548} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000549
550TYPED_TEST(HttpFetcherTest, PauseTest) {
Alex Deymof2858572016-02-25 11:20:13 -0800551 PausingHttpFetcherTestDelegate delegate;
552 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
553 delegate.paused_ = false;
554 delegate.fetcher_ = fetcher.get();
555 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000556
Alex Deymof2858572016-02-25 11:20:13 -0800557 unique_ptr<HttpServer> server(this->test_.CreateServer());
558 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800559
Alex Deymof2858572016-02-25 11:20:13 -0800560 MessageLoop::TaskId callback_id;
561 callback_id = this->loop_.PostDelayedTask(
562 FROM_HERE,
563 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
564 base::TimeDelta::FromMilliseconds(200));
565 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000566
Alex Deymof2858572016-02-25 11:20:13 -0800567 this->loop_.Run();
568 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
569}
570
571// This test will pause the fetcher while the download is not yet started
572// because it is waiting for the proxy to be resolved.
573TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
574 if (this->test_.IsMock())
575 return;
576 MockProxyResolver mock_resolver;
577 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver));
578
579 // Saved arguments from the proxy call.
580 ProxiesResolvedFn proxy_callback = nullptr;
581 void* proxy_data = nullptr;
582
583 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _, _))
584 .WillOnce(DoAll(
585 SaveArg<1>(&proxy_callback), SaveArg<2>(&proxy_data), Return(true)));
586 fetcher->BeginTransfer("http://fake_url");
587 testing::Mock::VerifyAndClearExpectations(&mock_resolver);
588
589 // Pausing and unpausing while resolving the proxy should not affect anything.
590 fetcher->Pause();
591 fetcher->Unpause();
592 fetcher->Pause();
593 // Proxy resolver comes back after we paused the fetcher.
594 ASSERT_TRUE(proxy_callback);
595 (*proxy_callback)({1, kNoProxy}, proxy_data);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000596}
597
598namespace {
599class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
600 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800601 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800602 const void* bytes, size_t length) override {}
Alex Deymo610277e2014-11-11 21:18:11 -0800603 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800604 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700605 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000606 }
Alex Deymo610277e2014-11-11 21:18:11 -0800607 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800608 EXPECT_EQ(fetcher, fetcher_.get());
609 EXPECT_FALSE(once_);
610 EXPECT_TRUE(callback_once_);
611 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700612 // The fetcher could have a callback scheduled on the ProxyResolver that
613 // can fire after this callback. We wait until the end of the test to
614 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800615 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000616 void TerminateTransfer() {
617 CHECK(once_);
618 once_ = false;
619 fetcher_->TerminateTransfer();
620 }
621 void EndLoop() {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700622 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000623 }
624 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800625 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700626 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000627};
628
Alex Deymo60ca1a72015-06-18 18:19:15 -0700629void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
630 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000631 if (delegate->once_) {
632 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700633 *my_id = MessageLoop::current()->PostTask(
634 FROM_HERE,
635 base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000636 } else {
637 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700638 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000639 }
640}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700641} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000642
643TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700644 AbortingHttpFetcherTestDelegate delegate;
645 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
646 delegate.once_ = true;
647 delegate.callback_once_ = true;
648 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000649
Alex Deymo60ca1a72015-06-18 18:19:15 -0700650 unique_ptr<HttpServer> server(this->test_.CreateServer());
651 this->test_.IgnoreServerAborting(server.get());
652 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800653
Alex Deymo60ca1a72015-06-18 18:19:15 -0700654 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000655
Alex Deymo60ca1a72015-06-18 18:19:15 -0700656 task_id = this->loop_.PostTask(
657 FROM_HERE,
658 base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
659 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
660
661 this->loop_.Run();
662 CHECK(!delegate.once_);
663 CHECK(!delegate.callback_once_);
664 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000665}
666
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000667namespace {
668class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
669 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800670 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800671 const void* bytes, size_t length) override {
672 data.append(reinterpret_cast<const char*>(bytes), length);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000673 }
Alex Deymo610277e2014-11-11 21:18:11 -0800674 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700675 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800676 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700677 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000678 }
Alex Deymo610277e2014-11-11 21:18:11 -0800679 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800680 ADD_FAILURE();
681 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000682 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000683};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700684} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000685
686TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800687 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000688 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000689 {
690 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700691 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000692 fetcher->set_delegate(&delegate);
693
Ben Chan02f7c1d2014-10-18 15:18:02 -0700694 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800695 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000696
Alex Deymo60ca1a72015-06-18 18:19:15 -0700697 this->loop_.PostTask(FROM_HERE, base::Bind(
698 &StartTransfer,
699 fetcher.get(),
700 LocalServerUrlForPath(server->GetPort(),
701 base::StringPrintf("/flaky/%d/%d/%d/%d",
702 kBigLength,
703 kFlakyTruncateLength,
704 kFlakySleepEvery,
705 kFlakySleepSecs))));
706 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000707
708 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800709 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800710 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000711 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
712 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
713 }
714 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000715}
716
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700717namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700718// This delegate kills the server attached to it after receiving any bytes.
719// This can be used for testing what happens when you try to fetch data and
720// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700721class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
722 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700723 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700724 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700725
Alex Deymo610277e2014-11-11 21:18:11 -0800726 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700727 if (server_) {
728 LOG(INFO) << "Stopping server in destructor";
729 delete server_;
730 LOG(INFO) << "server stopped";
731 }
732 }
733
Alex Deymo610277e2014-11-11 21:18:11 -0800734 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800735 const void* bytes, size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700736 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700737 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700738 delete server_;
739 LOG(INFO) << "server stopped";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700740 server_ = nullptr;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700741 }
742 }
Alex Deymo610277e2014-11-11 21:18:11 -0800743 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700744 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700745 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700746 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700747 }
Alex Deymo610277e2014-11-11 21:18:11 -0800748 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800749 ADD_FAILURE();
750 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700751 PythonHttpServer* server_;
752};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700753} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700754
755
756TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700757 // This test ensures that a fetcher responds correctly when a server isn't
758 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800759 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700760 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700761 {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700762 FailureHttpFetcherTestDelegate delegate(nullptr);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700763 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700764 fetcher->set_delegate(&delegate);
765
Alex Deymo60ca1a72015-06-18 18:19:15 -0700766 this->loop_.PostTask(FROM_HERE,
767 base::Bind(StartTransfer,
768 fetcher.get(),
769 "http://host_doesnt_exist99999999"));
770 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700771
772 // Exiting and testing happens in the delegate
773 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700774}
775
Alex Deymof123ae22015-09-24 14:59:43 -0700776TYPED_TEST(HttpFetcherTest, NoResponseTest) {
777 // This test starts a new http server but the server doesn't respond and just
778 // closes the connection.
779 if (this->test_.IsMock())
780 return;
781
782 PythonHttpServer* server = new PythonHttpServer();
783 int port = server->GetPort();
784 ASSERT_TRUE(server->started_);
785
786 // Handles destruction and claims ownership.
787 FailureHttpFetcherTestDelegate delegate(server);
788 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
789 fetcher->set_delegate(&delegate);
790 // The server will not reply at all, so we can limit the execution time of the
791 // test by reducing the low-speed timeout to something small. The test will
792 // finish once the TimeoutCallback() triggers (every second) and the timeout
793 // expired.
794 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
795
796 this->loop_.PostTask(FROM_HERE, base::Bind(
797 StartTransfer,
798 fetcher.get(),
799 LocalServerUrlForPath(port, "/hang")));
800 this->loop_.Run();
801
802 // Check that no other callback runs in the next two seconds. That would
803 // indicate a leaked callback.
804 bool timeout = false;
805 auto callback = base::Bind([&timeout]{ timeout = true;});
806 this->loop_.PostDelayedTask(FROM_HERE, callback,
807 base::TimeDelta::FromSeconds(2));
808 EXPECT_TRUE(this->loop_.RunOnce(true));
809 EXPECT_TRUE(timeout);
810}
811
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700812TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700813 // This test starts a new http server and kills it after receiving its first
814 // set of bytes. It test whether or not our fetcher eventually gives up on
815 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800816 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700817 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700818 {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700819 PythonHttpServer* server = new PythonHttpServer();
820 int port = server->GetPort();
821 ASSERT_TRUE(server->started_);
822
823 // Handles destruction and claims ownership.
824 FailureHttpFetcherTestDelegate delegate(server);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700825 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700826 fetcher->set_delegate(&delegate);
827
Alex Deymo60ca1a72015-06-18 18:19:15 -0700828 this->loop_.PostTask(FROM_HERE, base::Bind(
829 StartTransfer,
830 fetcher.get(),
831 LocalServerUrlForPath(port,
832 base::StringPrintf("/flaky/%d/%d/%d/%d",
833 kBigLength,
834 kFlakyTruncateLength,
835 kFlakySleepEvery,
836 kFlakySleepSecs))));
837 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700838
839 // Exiting and testing happens in the delegate
840 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700841}
842
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700843namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800844const HttpResponseCode kRedirectCodes[] = {
845 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
846 kHttpResponseTempRedirect
847};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700848
849class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
850 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700851 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700852 : expected_successful_(expected_successful) {}
Alex Deymo610277e2014-11-11 21:18:11 -0800853 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800854 const void* bytes, size_t length) override {
855 data.append(reinterpret_cast<const char*>(bytes), length);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700856 }
Alex Deymo610277e2014-11-11 21:18:11 -0800857 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700858 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700859 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800860 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700861 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800862 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
863 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700864 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700865 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700866 }
Alex Deymo610277e2014-11-11 21:18:11 -0800867 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800868 ADD_FAILURE();
869 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700870 bool expected_successful_;
871 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700872};
873
874// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700875void RedirectTest(const HttpServer* server,
876 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700877 const string& url,
878 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700879 RedirectHttpFetcherTestDelegate delegate(expected_successful);
880 unique_ptr<HttpFetcher> fetcher(http_fetcher);
881 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700882
Alex Deymo60ca1a72015-06-18 18:19:15 -0700883 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
884 StartTransfer,
885 fetcher.get(),
886 LocalServerUrlForPath(server->GetPort(), url)));
887 MessageLoop::current()->Run();
888 if (expected_successful) {
889 // verify the data we get back
Alex Deymo80f70ff2016-02-10 16:08:11 -0800890 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700891 for (int i = 0; i < kMediumLength; i += 10) {
892 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
893 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700894 }
895 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700896}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700897} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700898
899TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800900 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700901 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800902
Ben Chan02f7c1d2014-10-18 15:18:02 -0700903 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800904 ASSERT_TRUE(server->started_);
905
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700906 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800907 const string url = base::StringPrintf("/redirect/%d/download/%d",
908 kRedirectCodes[c],
909 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700910 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700911 }
912}
913
914TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800915 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700916 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800917
Ben Chan02f7c1d2014-10-18 15:18:02 -0700918 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800919 ASSERT_TRUE(server->started_);
920
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700921 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700922 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700923 url += base::StringPrintf("/redirect/%d",
924 kRedirectCodes[r % arraysize(kRedirectCodes)]);
925 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800926 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700927 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700928}
929
930TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800931 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700932 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800933
Ben Chan02f7c1d2014-10-18 15:18:02 -0700934 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800935 ASSERT_TRUE(server->started_);
936
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700937 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700938 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700939 url += base::StringPrintf("/redirect/%d",
940 kRedirectCodes[r % arraysize(kRedirectCodes)]);
941 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800942 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700943 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700944}
945
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700946namespace {
947class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
948 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700949 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700950 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800951
Alex Deymo610277e2014-11-11 21:18:11 -0800952 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800953 const void* bytes, size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800954 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800955 data.append(reinterpret_cast<const char*>(bytes), length);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700956 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800957
Alex Deymo610277e2014-11-11 21:18:11 -0800958 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800959 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800960 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700961 if (expected_response_code_ != 0)
962 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800963 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700964 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -0700965 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700966 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800967
Alex Deymo610277e2014-11-11 21:18:11 -0800968 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800969 ADD_FAILURE();
970 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800971
Ben Chan02f7c1d2014-10-18 15:18:02 -0700972 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700973 int expected_response_code_;
974 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700975};
976
977void MultiTest(HttpFetcher* fetcher_in,
Alex Deymoc1c17b42015-11-23 03:53:15 -0300978 FakeHardware* fake_hardware,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700979 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -0700980 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700981 const string& expected_prefix,
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800982 size_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800983 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700984 MultiHttpFetcherTestDelegate delegate(expected_response_code);
985 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -0700986
Alex Deymo60ca1a72015-06-18 18:19:15 -0700987 MultiRangeHttpFetcher* multi_fetcher =
Alex Deymo80f70ff2016-02-10 16:08:11 -0800988 static_cast<MultiRangeHttpFetcher*>(fetcher_in);
Alex Deymo60ca1a72015-06-18 18:19:15 -0700989 ASSERT_TRUE(multi_fetcher);
990 multi_fetcher->ClearRanges();
991 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
992 e = ranges.end(); it != e; ++it) {
993 string tmp_str = base::StringPrintf("%jd+", it->first);
994 if (it->second > 0) {
995 base::StringAppendF(&tmp_str, "%jd", it->second);
996 multi_fetcher->AddRange(it->first, it->second);
997 } else {
998 base::StringAppendF(&tmp_str, "?");
999 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001000 }
Alex Deymo60ca1a72015-06-18 18:19:15 -07001001 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001002 }
Alex Deymoc1c17b42015-11-23 03:53:15 -03001003 fake_hardware->SetIsOfficialBuild(false);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001004 multi_fetcher->set_delegate(&delegate);
1005
1006 MessageLoop::current()->PostTask(
1007 FROM_HERE,
1008 base::Bind(StartTransfer, multi_fetcher, url));
1009 MessageLoop::current()->Run();
1010
1011 EXPECT_EQ(expected_size, delegate.data.size());
1012 EXPECT_EQ(expected_prefix,
1013 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001014}
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001015} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001016
Darin Petkov9ce452b2010-11-17 14:33:28 -08001017TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001018 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001019 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001020
Ben Chan02f7c1d2014-10-18 15:18:02 -07001021 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001022 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001023
Ben Chanf9cb98c2014-09-21 18:31:30 -07001024 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001025 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001026 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001027 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001028 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001029 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001030 ranges,
1031 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001032 kBigLength - (99 - 25),
1033 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001034}
1035
1036TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001037 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001038 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001039
Ben Chan02f7c1d2014-10-18 15:18:02 -07001040 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001041 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001042
Ben Chanf9cb98c2014-09-21 18:31:30 -07001043 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001044 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001045 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001046 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001047 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001048 ranges,
1049 "abcdefghijabcdefghijabcd",
1050 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001051 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001052}
1053
1054TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001055 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001056 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001057
Ben Chan02f7c1d2014-10-18 15:18:02 -07001058 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001059 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001060
Ben Chanf9cb98c2014-09-21 18:31:30 -07001061 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001062 ranges.push_back(make_pair(kBigLength - 2, 0));
1063 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001064 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001065 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001066 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001067 ranges,
1068 "ijhij",
1069 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001070 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001071}
1072
1073TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001074 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001075 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001076
Ben Chan02f7c1d2014-10-18 15:18:02 -07001077 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001078 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001079
Ben Chanf9cb98c2014-09-21 18:31:30 -07001080 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001081 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001082 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001083 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001084 MultiTest(this->test_.NewLargeFetcher(),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001085 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001086 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001087 ranges,
1088 "ij",
1089 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001090 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001091 ranges.push_back(make_pair(0, 5));
1092 }
1093}
1094
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001095// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1096// should retry with other proxies listed before giving up.
1097//
1098// (1) successful recovery: The offset fetch will fail twice but succeed with
1099// the third proxy.
1100TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1101 if (!this->test_.IsMulti())
1102 return;
1103
Ben Chan02f7c1d2014-10-18 15:18:02 -07001104 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001105 ASSERT_TRUE(server->started_);
1106
Ben Chanf9cb98c2014-09-21 18:31:30 -07001107 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001108 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001109 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001110 MultiTest(this->test_.NewLargeFetcher(3),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001111 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001112 LocalServerUrlForPath(server->GetPort(),
1113 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001114 kBigLength)),
1115 ranges,
1116 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1117 kBigLength - (99 - 25),
1118 kHttpResponsePartialContent);
1119}
1120
1121// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1122// fetcher will signal a (failed) completed transfer to the delegate.
1123TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1124 if (!this->test_.IsMulti())
1125 return;
1126
Ben Chan02f7c1d2014-10-18 15:18:02 -07001127 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001128 ASSERT_TRUE(server->started_);
1129
Ben Chanf9cb98c2014-09-21 18:31:30 -07001130 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001131 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001132 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001133 MultiTest(this->test_.NewLargeFetcher(2),
Alex Deymoc1c17b42015-11-23 03:53:15 -03001134 this->test_.fake_hardware(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001135 LocalServerUrlForPath(server->GetPort(),
1136 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001137 kBigLength)),
1138 ranges,
1139 "abcdefghijabcdefghijabcde", // only received the first chunk
1140 25,
1141 kHttpResponseUndefined);
1142}
1143
1144
1145
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001146namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001147class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001148 public:
Alex Deymo610277e2014-11-11 21:18:11 -08001149 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001150 const void* bytes, size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001151 ADD_FAILURE();
1152 }
Alex Deymo610277e2014-11-11 21:18:11 -08001153 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001154 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001155 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001156 }
Alex Deymo610277e2014-11-11 21:18:11 -08001157 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001158 ADD_FAILURE();
1159 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001160};
1161
Alex Deymo60ca1a72015-06-18 18:19:15 -07001162void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1163 bool is_official_build) {
1164 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1165 return;
1166
1167 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1168 ASSERT_TRUE(server->started_);
1169
1170 BlockedTransferTestDelegate delegate;
1171 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1172 LOG(INFO) << "is_official_build: " << is_official_build;
1173 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
Alex Deymoc1c17b42015-11-23 03:53:15 -03001174 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001175 fetcher->set_delegate(&delegate);
1176
1177 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1178 StartTransfer,
1179 fetcher.get(),
1180 LocalServerUrlForPath(server->GetPort(),
1181 fetcher_test->SmallUrl(server->GetPort()))));
1182 MessageLoop::current()->Run();
1183}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001184} // namespace
1185
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001186TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001187 BlockedTransferTestHelper(&this->test_, false);
1188}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001189
Alex Deymo60ca1a72015-06-18 18:19:15 -07001190TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1191 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001192}
1193
rspangler@google.com49fdf182009-10-10 00:57:34 +00001194} // namespace chromeos_update_engine