blob: fd520e974c80d85a45dd61c14bab8702edcfd262 [file] [log] [blame]
Mike Frysinger8155d082012-04-06 15:23:18 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
rspangler@google.com49fdf182009-10-10 00:57:34 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07005#include <netinet/in.h>
6#include <netinet/ip.h>
7#include <sys/socket.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +00008#include <unistd.h>
Darin Petkov41c2fcf2010-08-25 13:14:48 -07009
Ben Chan02f7c1d2014-10-18 15:18:02 -070010#include <memory>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000011#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070012#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000013#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070014
Alex Deymo60ca1a72015-06-18 18:19:15 -070015#include <base/location.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080016#include <base/logging.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070017#include <base/strings/string_util.h>
18#include <base/strings/stringprintf.h>
19#include <base/time/time.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070020#include <chromeos/message_loops/glib_message_loop.h>
21#include <chromeos/message_loops/message_loop.h>
22#include <chromeos/message_loops/message_loop_utils.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080023#include <glib.h>
24#include <gtest/gtest.h>
25
Gilad Arnold5bb4c902014-04-10 12:32:13 -070026#include "update_engine/fake_system_state.h"
Gilad Arnold9bedeb52011-11-17 16:19:57 -080027#include "update_engine/http_common.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000028#include "update_engine/libcurl_http_fetcher.h"
29#include "update_engine/mock_http_fetcher.h"
Andrew de los Reyes819fef22010-12-17 11:33:58 -080030#include "update_engine/multi_range_http_fetcher.h"
Andrew de los Reyes45168102010-11-22 11:13:50 -080031#include "update_engine/proxy_resolver.h"
Jay Srinivasan08fce042012-06-07 16:31:01 -070032#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000033
Alex Deymo60ca1a72015-06-18 18:19:15 -070034using chromeos::MessageLoop;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070035using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080036using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000037using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070038using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000039using std::vector;
40
Gilad Arnold9bedeb52011-11-17 16:19:57 -080041namespace {
42
43const int kBigLength = 100000;
44const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080045const int kFlakyTruncateLength = 29000;
46const int kFlakySleepEvery = 3;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080047const int kFlakySleepSecs = 10;
48
49} // namespace
50
rspangler@google.com49fdf182009-10-10 00:57:34 +000051namespace chromeos_update_engine {
52
Gilad Arnold9bedeb52011-11-17 16:19:57 -080053static const char *kUnusedUrl = "unused://unused";
54
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070055static inline string LocalServerUrlForPath(in_port_t port,
56 const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070057 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070058 return base::StringPrintf("http://127.0.0.1%s%s", port_str.c_str(),
59 path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000060}
61
Gilad Arnold9bedeb52011-11-17 16:19:57 -080062//
63// Class hierarchy for HTTP server implementations.
64//
65
66class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000067 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080068 // This makes it an abstract class (dirty but works).
69 virtual ~HttpServer() = 0;
70
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070071 virtual in_port_t GetPort() const {
72 return 0;
73 }
74
rspangler@google.com49fdf182009-10-10 00:57:34 +000075 bool started_;
76};
77
Gilad Arnold9bedeb52011-11-17 16:19:57 -080078HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +000079
Gilad Arnold9bedeb52011-11-17 16:19:57 -080080
81class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000082 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080083 NullHttpServer() {
84 started_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +000085 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000086};
87
Gilad Arnold9bedeb52011-11-17 16:19:57 -080088
89class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000090 public:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070091 PythonHttpServer() : pid_(-1), port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000092 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070093
94 // Spawn the server process.
95 gchar *argv[] = {
96 const_cast<gchar*>("./test_http_server"),
Alex Vakulenko88b591f2014-08-28 16:48:57 -070097 nullptr
98 };
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070099 GError *err;
100 gint server_stdout = -1;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700101 if (!g_spawn_async_with_pipes(nullptr, argv, nullptr,
102 G_SPAWN_DO_NOT_REAP_CHILD, nullptr, nullptr,
103 &pid_, nullptr, &server_stdout, nullptr,
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700104 &err)) {
105 LOG(ERROR) << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000106 return;
107 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700108 CHECK_GT(pid_, 0);
109 CHECK_GE(server_stdout, 0);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700110 LOG(INFO) << "started http server with pid " << pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700111
112 // Wait for server to begin accepting connections, obtain its port.
113 char line[80];
114 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
115 CHECK_GT(sizeof(line), listening_msg_prefix_len);
116 int line_len = read(server_stdout, line, sizeof(line) - 1);
117 if (line_len <= static_cast<int>(listening_msg_prefix_len)) {
118 if (line_len < 0) {
Alex Deymo18f48aa2015-04-09 10:06:31 -0700119 PLOG(ERROR) << "error reading http server stdout";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700120 } else {
121 LOG(ERROR) << "server output too short";
122 }
123 Terminate(true);
124 return;
125 }
126
127 line[line_len] = '\0';
128 CHECK_EQ(strstr(line, kServerListeningMsgPrefix), line);
129 const char* listening_port_str = line + listening_msg_prefix_len;
130 char* end_ptr;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700131 long raw_port = strtol(listening_port_str, // NOLINT(runtime/int)
132 &end_ptr, 10);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700133 CHECK(!*end_ptr || *end_ptr == '\n');
134 port_ = static_cast<in_port_t>(raw_port);
135 CHECK_GT(port_, 0);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700136 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700137 LOG(INFO) << "server running, listening on port " << port_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700138 LOG(INFO) << "gdb attach now!";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000139 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800140
rspangler@google.com49fdf182009-10-10 00:57:34 +0000141 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700142 // If there's no process, do nothing.
143 if (pid_ == -1)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000144 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700145
146 // If server is responsive, request that it gracefully terminate.
147 bool do_kill = false;
148 if (started_) {
149 LOG(INFO) << "running wget to exit";
150 if (system((string("wget -t 1 --output-document=/dev/null ") +
151 LocalServerUrlForPath(port_, "/quitquitquit")).c_str())) {
152 LOG(WARNING) << "wget failed, resorting to brute force";
153 do_kill = true;
154 }
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700155 }
156
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700157 // Server not responding or wget failed, kill the process.
158 Terminate(do_kill);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000159 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800160
Alex Deymo610277e2014-11-11 21:18:11 -0800161 in_port_t GetPort() const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700162 return port_;
163 }
164
165 private:
166 void Terminate(bool do_kill) {
167 ASSERT_GT(pid_, 0);
168
169 if (do_kill) {
170 LOG(INFO) << "terminating (SIGKILL) server process with pid " << pid_;
171 kill(pid_, SIGKILL);
172 }
173
174 LOG(INFO) << "waiting for http server with pid " << pid_ << " to terminate";
175 int status;
176 pid_t killed_pid = waitpid(pid_, &status, 0);
177 ASSERT_EQ(killed_pid, pid_);
178 LOG(INFO) << "http server with pid " << pid_
179 << " terminated with status " << status;
180 pid_ = -1;
181 }
182
183 static const char* kServerListeningMsgPrefix;
184
rspangler@google.com49fdf182009-10-10 00:57:34 +0000185 GPid pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700186 in_port_t port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000187};
188
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700189const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
190
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800191//
192// Class hierarchy for HTTP fetcher test wrappers.
193//
194
195class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000196 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700197 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700198 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700199
Alex Deymo7984bf02014-04-02 20:41:57 -0700200 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800201 HttpFetcher* NewLargeFetcher() {
202 return NewLargeFetcher(1);
203 }
204
205 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) = 0;
206 HttpFetcher* NewSmallFetcher() {
207 return NewSmallFetcher(1);
208 }
209
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700210 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
211 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
212 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800213
214 virtual bool IsMock() const = 0;
215 virtual bool IsMulti() const = 0;
216
217 virtual void IgnoreServerAborting(HttpServer* server) const {}
218
Alex Deymo60ca1a72015-06-18 18:19:15 -0700219 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800220
221 protected:
222 DirectProxyResolver proxy_resolver_;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700223 FakeSystemState fake_system_state_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800224};
225
226class MockHttpFetcherTest : public AnyHttpFetcherTest {
227 public:
228 // Necessary to unhide the definition in the base class.
229 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800230 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800231 chromeos::Blob big_data(1000000);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700232 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800233 proxy_resolver_.set_num_proxies(num_proxies);
234 return new MockHttpFetcher(
235 big_data.data(),
236 big_data.size(),
237 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
238 }
239
240 // Necessary to unhide the definition in the base class.
241 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800242 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700243 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800244 proxy_resolver_.set_num_proxies(num_proxies);
245 return new MockHttpFetcher(
246 "x",
247 1,
248 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
249 }
250
Alex Deymo610277e2014-11-11 21:18:11 -0800251 bool IsMock() const override { return true; }
252 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800253
Alex Deymo60ca1a72015-06-18 18:19:15 -0700254 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800255 return new NullHttpServer;
256 }
257};
258
259class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
260 public:
261 // Necessary to unhide the definition in the base class.
262 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800263 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700264 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800265 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes45168102010-11-22 11:13:50 -0800266 LibcurlHttpFetcher *ret = new
Jay Srinivasan08fce042012-06-07 16:31:01 -0700267 LibcurlHttpFetcher(reinterpret_cast<ProxyResolver*>(&proxy_resolver_),
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700268 &fake_system_state_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700269 // Speed up test execution.
270 ret->set_idle_seconds(1);
271 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700272 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000273 return ret;
274 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800275
276 // Necessary to unhide the definition in the base class.
277 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800278 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800279 return NewLargeFetcher(num_proxies);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000280 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800281
Alex Deymo610277e2014-11-11 21:18:11 -0800282 string BigUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700283 return LocalServerUrlForPath(port,
284 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800285 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000286 }
Alex Deymo610277e2014-11-11 21:18:11 -0800287 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700288 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000289 }
Alex Deymo610277e2014-11-11 21:18:11 -0800290 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700291 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800292 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800293
Alex Deymo610277e2014-11-11 21:18:11 -0800294 bool IsMock() const override { return false; }
295 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800296
Alex Deymo610277e2014-11-11 21:18:11 -0800297 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700298 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700299 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800300
Alex Deymo60ca1a72015-06-18 18:19:15 -0700301 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800302 return new PythonHttpServer;
303 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000304};
305
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800306class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700307 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800308 // Necessary to unhide the definition in the base class.
309 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800310 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700311 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800312 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800313 ProxyResolver* resolver =
314 reinterpret_cast<ProxyResolver*>(&proxy_resolver_);
Gilad Arnold7c04e762012-05-23 10:54:02 -0700315 MultiRangeHttpFetcher *ret =
316 new MultiRangeHttpFetcher(
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700317 new LibcurlHttpFetcher(resolver, &fake_system_state_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800318 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800319 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700320 // Speed up test execution.
321 ret->set_idle_seconds(1);
322 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700323 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700324 return ret;
325 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800326
327 // Necessary to unhide the definition in the base class.
328 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800329 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800330 return NewLargeFetcher(num_proxies);
331 }
332
Alex Deymo610277e2014-11-11 21:18:11 -0800333 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700334};
335
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800336
337//
338// Infrastructure for type tests of HTTP fetcher.
339// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
340//
341
342// Fixture class template. We use an explicit constraint to guarantee that it
343// can only be instantiated with an AnyHttpFetcherTest type, see:
344// http://www2.research.att.com/~bs/bs_faq2.html#constraints
345template <typename T>
346class HttpFetcherTest : public ::testing::Test {
347 public:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700348 // TODO(deymo): Replace this with a FakeMessageLoop. We can't do that yet
349 // because these tests use g_spawn_async_with_pipes() to launch the
350 // http_test_server.
351 chromeos::GlibMessageLoop loop_;
352
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800353 T test_;
354
Alex Deymo60ca1a72015-06-18 18:19:15 -0700355 protected:
356 HttpFetcherTest() {
357 loop_.SetAsCurrent();
358 }
359
360 void TearDown() override {
361 EXPECT_EQ(0, chromeos::MessageLoopRunMaxIterations(&loop_, 1));
362 }
363
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800364 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700365 static void TypeConstraint(T* a) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800366 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700367 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700368 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800369 }
370};
371
372// Test case types list.
373typedef ::testing::Types<LibcurlHttpFetcherTest,
374 MockHttpFetcherTest,
375 MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000376TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
377
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800378
rspangler@google.com49fdf182009-10-10 00:57:34 +0000379namespace {
380class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000381 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800382 HttpFetcherTestDelegate() :
Gilad Arnold48085ba2011-11-16 09:36:08 -0800383 is_expect_error_(false), times_transfer_complete_called_(0),
384 times_transfer_terminated_called_(0), times_received_bytes_called_(0) {}
385
Alex Deymo610277e2014-11-11 21:18:11 -0800386 void ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800387 const void* /* bytes */, size_t /* length */) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800388 // Update counters
389 times_received_bytes_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 TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800393 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800394 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800395 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800396 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700397 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800398
399 // Update counter
400 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000401 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800402
Alex Deymo610277e2014-11-11 21:18:11 -0800403 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800404 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800405 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800406 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800407
Gilad Arnold48085ba2011-11-16 09:36:08 -0800408 // Are we expecting an error response? (default: no)
409 bool is_expect_error_;
410
411 // Counters for callback invocations.
412 int times_transfer_complete_called_;
413 int times_transfer_terminated_called_;
414 int times_received_bytes_called_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000415};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000416
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000417
Alex Deymo60ca1a72015-06-18 18:19:15 -0700418void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
419 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000420}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700421} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000422
423TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700424 HttpFetcherTestDelegate delegate;
425 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
426 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000427
Alex Deymo60ca1a72015-06-18 18:19:15 -0700428 unique_ptr<HttpServer> server(this->test_.CreateServer());
429 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000430
Alex Deymo60ca1a72015-06-18 18:19:15 -0700431 this->loop_.PostTask(FROM_HERE, base::Bind(
432 StartTransfer,
433 fetcher.get(),
434 this->test_.SmallUrl(server->GetPort())));
435 this->loop_.Run();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000436}
437
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700438TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700439 HttpFetcherTestDelegate delegate;
440 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
441 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700442
Alex Deymo60ca1a72015-06-18 18:19:15 -0700443 unique_ptr<HttpServer> server(this->test_.CreateServer());
444 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700445
Alex Deymo60ca1a72015-06-18 18:19:15 -0700446 this->loop_.PostTask(FROM_HERE, base::Bind(
447 StartTransfer,
448 fetcher.get(),
449 this->test_.BigUrl(server->GetPort())));
450 this->loop_.Run();
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700451}
452
Gilad Arnold48085ba2011-11-16 09:36:08 -0800453// Issue #9648: when server returns an error HTTP response, the fetcher needs to
454// terminate transfer prematurely, rather than try to process the error payload.
455TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800456 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800457 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700458 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800459
Alex Deymo60ca1a72015-06-18 18:19:15 -0700460 // Delegate should expect an error response.
461 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800462
Alex Deymo60ca1a72015-06-18 18:19:15 -0700463 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
464 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800465
Alex Deymo60ca1a72015-06-18 18:19:15 -0700466 unique_ptr<HttpServer> server(this->test_.CreateServer());
467 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800468
Alex Deymo60ca1a72015-06-18 18:19:15 -0700469 this->loop_.PostTask(FROM_HERE, base::Bind(
470 StartTransfer,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800471 fetcher.get(),
Alex Deymo60ca1a72015-06-18 18:19:15 -0700472 this->test_.ErrorUrl(server->GetPort())));
473 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800474
Alex Deymo60ca1a72015-06-18 18:19:15 -0700475 // Make sure that no bytes were received.
476 CHECK_EQ(delegate.times_received_bytes_called_, 0);
477 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800478
Alex Deymo60ca1a72015-06-18 18:19:15 -0700479 // Make sure that transfer completion was signaled once, and no termination
480 // was signaled.
481 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
482 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800483}
484
rspangler@google.com49fdf182009-10-10 00:57:34 +0000485namespace {
486class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
487 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800488 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800489 const void* /* bytes */, size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000490 CHECK(!paused_);
491 paused_ = true;
492 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000493 }
Alex Deymo610277e2014-11-11 21:18:11 -0800494 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700495 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000496 }
Alex Deymo610277e2014-11-11 21:18:11 -0800497 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800498 ADD_FAILURE();
499 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000500 void Unpause() {
501 CHECK(paused_);
502 paused_ = false;
503 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000504 }
505 bool paused_;
506 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000507};
508
Alex Deymo60ca1a72015-06-18 18:19:15 -0700509void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
510 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000511 if (delegate->paused_)
512 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700513 // Update the task id with the new scheduled callback.
514 *my_id = MessageLoop::current()->PostDelayedTask(
515 FROM_HERE,
516 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
517 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000518}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700519} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000520
521TYPED_TEST(HttpFetcherTest, PauseTest) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000522 {
523 PausingHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700524 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000525 delegate.paused_ = false;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000526 delegate.fetcher_ = fetcher.get();
527 fetcher->set_delegate(&delegate);
528
Ben Chan02f7c1d2014-10-18 15:18:02 -0700529 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800530 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800531
Alex Deymo60ca1a72015-06-18 18:19:15 -0700532 MessageLoop::TaskId callback_id;
533 callback_id = this->loop_.PostDelayedTask(
534 FROM_HERE,
535 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
536 base::TimeDelta::FromMilliseconds(200));
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700537 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000538
Alex Deymo60ca1a72015-06-18 18:19:15 -0700539 this->loop_.Run();
540 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000541 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000542}
543
544namespace {
545class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
546 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800547 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800548 const void* bytes, size_t length) override {}
Alex Deymo610277e2014-11-11 21:18:11 -0800549 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800550 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700551 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000552 }
Alex Deymo610277e2014-11-11 21:18:11 -0800553 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800554 EXPECT_EQ(fetcher, fetcher_.get());
555 EXPECT_FALSE(once_);
556 EXPECT_TRUE(callback_once_);
557 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700558 // The fetcher could have a callback scheduled on the ProxyResolver that
559 // can fire after this callback. We wait until the end of the test to
560 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800561 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000562 void TerminateTransfer() {
563 CHECK(once_);
564 once_ = false;
565 fetcher_->TerminateTransfer();
566 }
567 void EndLoop() {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700568 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000569 }
570 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800571 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700572 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000573};
574
Alex Deymo60ca1a72015-06-18 18:19:15 -0700575void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
576 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000577 if (delegate->once_) {
578 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700579 *my_id = MessageLoop::current()->PostTask(
580 FROM_HERE,
581 base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000582 } else {
583 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700584 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000585 }
586}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700587} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000588
589TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700590 AbortingHttpFetcherTestDelegate delegate;
591 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
592 delegate.once_ = true;
593 delegate.callback_once_ = true;
594 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000595
Alex Deymo60ca1a72015-06-18 18:19:15 -0700596 unique_ptr<HttpServer> server(this->test_.CreateServer());
597 this->test_.IgnoreServerAborting(server.get());
598 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800599
Alex Deymo60ca1a72015-06-18 18:19:15 -0700600 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000601
Alex Deymo60ca1a72015-06-18 18:19:15 -0700602 task_id = this->loop_.PostTask(
603 FROM_HERE,
604 base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
605 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
606
607 this->loop_.Run();
608 CHECK(!delegate.once_);
609 CHECK(!delegate.callback_once_);
610 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000611}
612
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000613namespace {
614class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
615 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800616 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800617 const void* bytes, size_t length) override {
618 data.append(reinterpret_cast<const char*>(bytes), length);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000619 }
Alex Deymo610277e2014-11-11 21:18:11 -0800620 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700621 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800622 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700623 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000624 }
Alex Deymo610277e2014-11-11 21:18:11 -0800625 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800626 ADD_FAILURE();
627 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000628 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000629};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700630} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000631
632TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800633 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000634 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000635 {
636 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700637 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000638 fetcher->set_delegate(&delegate);
639
Ben Chan02f7c1d2014-10-18 15:18:02 -0700640 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800641 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000642
Alex Deymo60ca1a72015-06-18 18:19:15 -0700643 this->loop_.PostTask(FROM_HERE, base::Bind(
644 &StartTransfer,
645 fetcher.get(),
646 LocalServerUrlForPath(server->GetPort(),
647 base::StringPrintf("/flaky/%d/%d/%d/%d",
648 kBigLength,
649 kFlakyTruncateLength,
650 kFlakySleepEvery,
651 kFlakySleepSecs))));
652 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000653
654 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800655 ASSERT_EQ(kBigLength, delegate.data.size());
656 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000657 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
658 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
659 }
660 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000661}
662
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700663namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700664// This delegate kills the server attached to it after receiving any bytes.
665// This can be used for testing what happens when you try to fetch data and
666// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700667class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
668 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700669 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700670 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700671
Alex Deymo610277e2014-11-11 21:18:11 -0800672 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700673 if (server_) {
674 LOG(INFO) << "Stopping server in destructor";
675 delete server_;
676 LOG(INFO) << "server stopped";
677 }
678 }
679
Alex Deymo610277e2014-11-11 21:18:11 -0800680 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800681 const void* bytes, size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700682 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700683 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700684 delete server_;
685 LOG(INFO) << "server stopped";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700686 server_ = nullptr;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700687 }
688 }
Alex Deymo610277e2014-11-11 21:18:11 -0800689 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700690 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700691 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700692 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700693 }
Alex Deymo610277e2014-11-11 21:18:11 -0800694 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800695 ADD_FAILURE();
696 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700697 PythonHttpServer* server_;
698};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700699} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700700
701
702TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700703 // This test ensures that a fetcher responds correctly when a server isn't
704 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800705 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700706 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700707 {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700708 FailureHttpFetcherTestDelegate delegate(nullptr);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700709 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700710 fetcher->set_delegate(&delegate);
711
Alex Deymo60ca1a72015-06-18 18:19:15 -0700712 this->loop_.PostTask(FROM_HERE,
713 base::Bind(StartTransfer,
714 fetcher.get(),
715 "http://host_doesnt_exist99999999"));
716 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700717
718 // Exiting and testing happens in the delegate
719 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700720}
721
722TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700723 // This test starts a new http server and kills it after receiving its first
724 // set of bytes. It test whether or not our fetcher eventually gives up on
725 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800726 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700727 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700728 {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700729 PythonHttpServer* server = new PythonHttpServer();
730 int port = server->GetPort();
731 ASSERT_TRUE(server->started_);
732
733 // Handles destruction and claims ownership.
734 FailureHttpFetcherTestDelegate delegate(server);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700735 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700736 fetcher->set_delegate(&delegate);
737
Alex Deymo60ca1a72015-06-18 18:19:15 -0700738 this->loop_.PostTask(FROM_HERE, base::Bind(
739 StartTransfer,
740 fetcher.get(),
741 LocalServerUrlForPath(port,
742 base::StringPrintf("/flaky/%d/%d/%d/%d",
743 kBigLength,
744 kFlakyTruncateLength,
745 kFlakySleepEvery,
746 kFlakySleepSecs))));
747 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700748
749 // Exiting and testing happens in the delegate
750 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700751}
752
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700753namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800754const HttpResponseCode kRedirectCodes[] = {
755 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
756 kHttpResponseTempRedirect
757};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700758
759class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
760 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700761 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700762 : expected_successful_(expected_successful) {}
Alex Deymo610277e2014-11-11 21:18:11 -0800763 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800764 const void* bytes, size_t length) override {
765 data.append(reinterpret_cast<const char*>(bytes), length);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700766 }
Alex Deymo610277e2014-11-11 21:18:11 -0800767 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700768 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700769 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800770 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700771 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800772 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
773 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700774 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700775 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700776 }
Alex Deymo610277e2014-11-11 21:18:11 -0800777 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800778 ADD_FAILURE();
779 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700780 bool expected_successful_;
781 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700782};
783
784// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700785void RedirectTest(const HttpServer* server,
786 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700787 const string& url,
788 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700789 RedirectHttpFetcherTestDelegate delegate(expected_successful);
790 unique_ptr<HttpFetcher> fetcher(http_fetcher);
791 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700792
Alex Deymo60ca1a72015-06-18 18:19:15 -0700793 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
794 StartTransfer,
795 fetcher.get(),
796 LocalServerUrlForPath(server->GetPort(), url)));
797 MessageLoop::current()->Run();
798 if (expected_successful) {
799 // verify the data we get back
800 ASSERT_EQ(kMediumLength, delegate.data.size());
801 for (int i = 0; i < kMediumLength; i += 10) {
802 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
803 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700804 }
805 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700806}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700807} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700808
809TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800810 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700811 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800812
Ben Chan02f7c1d2014-10-18 15:18:02 -0700813 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800814 ASSERT_TRUE(server->started_);
815
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700816 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800817 const string url = base::StringPrintf("/redirect/%d/download/%d",
818 kRedirectCodes[c],
819 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700820 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700821 }
822}
823
824TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800825 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700826 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800827
Ben Chan02f7c1d2014-10-18 15:18:02 -0700828 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800829 ASSERT_TRUE(server->started_);
830
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700831 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700832 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700833 url += base::StringPrintf("/redirect/%d",
834 kRedirectCodes[r % arraysize(kRedirectCodes)]);
835 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800836 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700837 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700838}
839
840TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800841 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700842 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800843
Ben Chan02f7c1d2014-10-18 15:18:02 -0700844 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800845 ASSERT_TRUE(server->started_);
846
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700847 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700848 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700849 url += base::StringPrintf("/redirect/%d",
850 kRedirectCodes[r % arraysize(kRedirectCodes)]);
851 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800852 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700853 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700854}
855
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700856namespace {
857class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
858 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700859 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700860 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800861
Alex Deymo610277e2014-11-11 21:18:11 -0800862 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800863 const void* bytes, size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800864 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800865 data.append(reinterpret_cast<const char*>(bytes), length);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700866 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800867
Alex Deymo610277e2014-11-11 21:18:11 -0800868 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800869 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800870 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700871 if (expected_response_code_ != 0)
872 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800873 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700874 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -0700875 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700876 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800877
Alex Deymo610277e2014-11-11 21:18:11 -0800878 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800879 ADD_FAILURE();
880 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800881
Ben Chan02f7c1d2014-10-18 15:18:02 -0700882 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700883 int expected_response_code_;
884 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700885};
886
887void MultiTest(HttpFetcher* fetcher_in,
888 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -0700889 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700890 const string& expected_prefix,
891 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800892 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700893 MultiHttpFetcherTestDelegate delegate(expected_response_code);
894 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -0700895
Alex Deymo60ca1a72015-06-18 18:19:15 -0700896 MultiRangeHttpFetcher* multi_fetcher =
897 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
898 ASSERT_TRUE(multi_fetcher);
899 multi_fetcher->ClearRanges();
900 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
901 e = ranges.end(); it != e; ++it) {
902 string tmp_str = base::StringPrintf("%jd+", it->first);
903 if (it->second > 0) {
904 base::StringAppendF(&tmp_str, "%jd", it->second);
905 multi_fetcher->AddRange(it->first, it->second);
906 } else {
907 base::StringAppendF(&tmp_str, "?");
908 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800909 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700910 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700911 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700912 dynamic_cast<FakeSystemState*>(fetcher_in->GetSystemState())
913 ->fake_hardware()->SetIsOfficialBuild(false);
914 multi_fetcher->set_delegate(&delegate);
915
916 MessageLoop::current()->PostTask(
917 FROM_HERE,
918 base::Bind(StartTransfer, multi_fetcher, url));
919 MessageLoop::current()->Run();
920
921 EXPECT_EQ(expected_size, delegate.data.size());
922 EXPECT_EQ(expected_prefix,
923 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700924}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700925} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700926
Darin Petkov9ce452b2010-11-17 14:33:28 -0800927TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800928 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700929 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800930
Ben Chan02f7c1d2014-10-18 15:18:02 -0700931 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800932 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700933
Ben Chanf9cb98c2014-09-21 18:31:30 -0700934 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700935 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800936 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800937 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700938 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700939 ranges,
940 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800941 kBigLength - (99 - 25),
942 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700943}
944
945TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800946 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700947 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800948
Ben Chan02f7c1d2014-10-18 15:18:02 -0700949 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800950 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700951
Ben Chanf9cb98c2014-09-21 18:31:30 -0700952 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700953 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800954 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700955 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700956 ranges,
957 "abcdefghijabcdefghijabcd",
958 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800959 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700960}
961
962TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800963 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700964 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800965
Ben Chan02f7c1d2014-10-18 15:18:02 -0700966 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800967 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700968
Ben Chanf9cb98c2014-09-21 18:31:30 -0700969 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800970 ranges.push_back(make_pair(kBigLength - 2, 0));
971 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800972 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700973 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700974 ranges,
975 "ijhij",
976 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800977 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700978}
979
980TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800981 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700982 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800983
Ben Chan02f7c1d2014-10-18 15:18:02 -0700984 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800985 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700986
Ben Chanf9cb98c2014-09-21 18:31:30 -0700987 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800988 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700989 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800990 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800991 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700992 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700993 ranges,
994 "ij",
995 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800996 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700997 ranges.push_back(make_pair(0, 5));
998 }
999}
1000
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001001// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1002// should retry with other proxies listed before giving up.
1003//
1004// (1) successful recovery: The offset fetch will fail twice but succeed with
1005// the third proxy.
1006TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1007 if (!this->test_.IsMulti())
1008 return;
1009
Ben Chan02f7c1d2014-10-18 15:18:02 -07001010 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001011 ASSERT_TRUE(server->started_);
1012
Ben Chanf9cb98c2014-09-21 18:31:30 -07001013 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001014 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001015 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001016 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001017 LocalServerUrlForPath(server->GetPort(),
1018 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001019 kBigLength)),
1020 ranges,
1021 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1022 kBigLength - (99 - 25),
1023 kHttpResponsePartialContent);
1024}
1025
1026// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1027// fetcher will signal a (failed) completed transfer to the delegate.
1028TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1029 if (!this->test_.IsMulti())
1030 return;
1031
Ben Chan02f7c1d2014-10-18 15:18:02 -07001032 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001033 ASSERT_TRUE(server->started_);
1034
Ben Chanf9cb98c2014-09-21 18:31:30 -07001035 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001036 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001037 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001038 MultiTest(this->test_.NewLargeFetcher(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001039 LocalServerUrlForPath(server->GetPort(),
1040 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001041 kBigLength)),
1042 ranges,
1043 "abcdefghijabcdefghijabcde", // only received the first chunk
1044 25,
1045 kHttpResponseUndefined);
1046}
1047
1048
1049
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001050namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001051class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001052 public:
Alex Deymo610277e2014-11-11 21:18:11 -08001053 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001054 const void* bytes, size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001055 ADD_FAILURE();
1056 }
Alex Deymo610277e2014-11-11 21:18:11 -08001057 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001058 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001059 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001060 }
Alex Deymo610277e2014-11-11 21:18:11 -08001061 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001062 ADD_FAILURE();
1063 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001064};
1065
Alex Deymo60ca1a72015-06-18 18:19:15 -07001066void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1067 bool is_official_build) {
1068 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1069 return;
1070
1071 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1072 ASSERT_TRUE(server->started_);
1073
1074 BlockedTransferTestDelegate delegate;
1075 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1076 LOG(INFO) << "is_official_build: " << is_official_build;
1077 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
1078 dynamic_cast<FakeSystemState*>(fetcher->GetSystemState())
1079 ->fake_hardware()->SetIsOfficialBuild(is_official_build);
1080 fetcher->set_delegate(&delegate);
1081
1082 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1083 StartTransfer,
1084 fetcher.get(),
1085 LocalServerUrlForPath(server->GetPort(),
1086 fetcher_test->SmallUrl(server->GetPort()))));
1087 MessageLoop::current()->Run();
1088}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001089} // namespace
1090
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001091TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001092 BlockedTransferTestHelper(&this->test_, false);
1093}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001094
Alex Deymo60ca1a72015-06-18 18:19:15 -07001095TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1096 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001097}
1098
rspangler@google.com49fdf182009-10-10 00:57:34 +00001099} // namespace chromeos_update_engine