blob: a50654e38a3d294a537685d94c700872a990102f [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
Andrew de los Reyes45168102010-11-22 11:13:50 -080015#include <base/logging.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070016#include <base/strings/string_util.h>
17#include <base/strings/stringprintf.h>
18#include <base/time/time.h>
Jay Srinivasan43488792012-06-19 00:25:31 -070019#include <chromeos/dbus/service_constants.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080020#include <glib.h>
21#include <gtest/gtest.h>
22
Gilad Arnold5bb4c902014-04-10 12:32:13 -070023#include "update_engine/fake_system_state.h"
Gilad Arnold9bedeb52011-11-17 16:19:57 -080024#include "update_engine/http_common.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000025#include "update_engine/libcurl_http_fetcher.h"
26#include "update_engine/mock_http_fetcher.h"
Andrew de los Reyes819fef22010-12-17 11:33:58 -080027#include "update_engine/multi_range_http_fetcher.h"
Andrew de los Reyes45168102010-11-22 11:13:50 -080028#include "update_engine/proxy_resolver.h"
Jay Srinivasan08fce042012-06-07 16:31:01 -070029#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000030
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070031using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080032using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000033using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070034using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000035using std::vector;
36
Jay Srinivasan43488792012-06-19 00:25:31 -070037
Gilad Arnold9bedeb52011-11-17 16:19:57 -080038namespace {
39
40const int kBigLength = 100000;
41const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080042const int kFlakyTruncateLength = 29000;
43const int kFlakySleepEvery = 3;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080044const int kFlakySleepSecs = 10;
45
46} // namespace
47
rspangler@google.com49fdf182009-10-10 00:57:34 +000048namespace chromeos_update_engine {
49
Gilad Arnold9bedeb52011-11-17 16:19:57 -080050static const char *kUnusedUrl = "unused://unused";
51
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070052static inline string LocalServerUrlForPath(in_port_t port,
53 const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070054 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070055 return base::StringPrintf("http://127.0.0.1%s%s", port_str.c_str(),
56 path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000057}
58
Gilad Arnold9bedeb52011-11-17 16:19:57 -080059//
60// Class hierarchy for HTTP server implementations.
61//
62
63class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000064 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080065 // This makes it an abstract class (dirty but works).
66 virtual ~HttpServer() = 0;
67
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070068 virtual in_port_t GetPort() const {
69 return 0;
70 }
71
rspangler@google.com49fdf182009-10-10 00:57:34 +000072 bool started_;
73};
74
Gilad Arnold9bedeb52011-11-17 16:19:57 -080075HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +000076
Gilad Arnold9bedeb52011-11-17 16:19:57 -080077
78class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000079 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080080 NullHttpServer() {
81 started_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +000082 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000083};
84
Gilad Arnold9bedeb52011-11-17 16:19:57 -080085
86class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000087 public:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070088 PythonHttpServer() : pid_(-1), port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000089 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070090
91 // Spawn the server process.
92 gchar *argv[] = {
93 const_cast<gchar*>("./test_http_server"),
Alex Vakulenko88b591f2014-08-28 16:48:57 -070094 nullptr
95 };
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070096 GError *err;
97 gint server_stdout = -1;
Alex Vakulenko88b591f2014-08-28 16:48:57 -070098 if (!g_spawn_async_with_pipes(nullptr, argv, nullptr,
99 G_SPAWN_DO_NOT_REAP_CHILD, nullptr, nullptr,
100 &pid_, nullptr, &server_stdout, nullptr,
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700101 &err)) {
102 LOG(ERROR) << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000103 return;
104 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700105 CHECK_GT(pid_, 0);
106 CHECK_GE(server_stdout, 0);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700107 LOG(INFO) << "started http server with pid " << pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700108
109 // Wait for server to begin accepting connections, obtain its port.
110 char line[80];
111 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
112 CHECK_GT(sizeof(line), listening_msg_prefix_len);
113 int line_len = read(server_stdout, line, sizeof(line) - 1);
114 if (line_len <= static_cast<int>(listening_msg_prefix_len)) {
115 if (line_len < 0) {
116 LOG(ERROR) << "error reading http server stdout: "
117 << strerror(errno);
118 } else {
119 LOG(ERROR) << "server output too short";
120 }
121 Terminate(true);
122 return;
123 }
124
125 line[line_len] = '\0';
126 CHECK_EQ(strstr(line, kServerListeningMsgPrefix), line);
127 const char* listening_port_str = line + listening_msg_prefix_len;
128 char* end_ptr;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700129 long raw_port = strtol(listening_port_str, // NOLINT(runtime/int)
130 &end_ptr, 10);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700131 CHECK(!*end_ptr || *end_ptr == '\n');
132 port_ = static_cast<in_port_t>(raw_port);
133 CHECK_GT(port_, 0);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700134 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700135 LOG(INFO) << "server running, listening on port " << port_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700136 LOG(INFO) << "gdb attach now!";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000137 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800138
rspangler@google.com49fdf182009-10-10 00:57:34 +0000139 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700140 // If there's no process, do nothing.
141 if (pid_ == -1)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000142 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700143
144 // If server is responsive, request that it gracefully terminate.
145 bool do_kill = false;
146 if (started_) {
147 LOG(INFO) << "running wget to exit";
148 if (system((string("wget -t 1 --output-document=/dev/null ") +
149 LocalServerUrlForPath(port_, "/quitquitquit")).c_str())) {
150 LOG(WARNING) << "wget failed, resorting to brute force";
151 do_kill = true;
152 }
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700153 }
154
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700155 // Server not responding or wget failed, kill the process.
156 Terminate(do_kill);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000157 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800158
Alex Deymo610277e2014-11-11 21:18:11 -0800159 in_port_t GetPort() const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700160 return port_;
161 }
162
163 private:
164 void Terminate(bool do_kill) {
165 ASSERT_GT(pid_, 0);
166
167 if (do_kill) {
168 LOG(INFO) << "terminating (SIGKILL) server process with pid " << pid_;
169 kill(pid_, SIGKILL);
170 }
171
172 LOG(INFO) << "waiting for http server with pid " << pid_ << " to terminate";
173 int status;
174 pid_t killed_pid = waitpid(pid_, &status, 0);
175 ASSERT_EQ(killed_pid, pid_);
176 LOG(INFO) << "http server with pid " << pid_
177 << " terminated with status " << status;
178 pid_ = -1;
179 }
180
181 static const char* kServerListeningMsgPrefix;
182
rspangler@google.com49fdf182009-10-10 00:57:34 +0000183 GPid pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700184 in_port_t port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000185};
186
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700187const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
188
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800189//
190// Class hierarchy for HTTP fetcher test wrappers.
191//
192
193class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000194 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700195 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700196 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700197
Alex Deymo7984bf02014-04-02 20:41:57 -0700198 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800199 HttpFetcher* NewLargeFetcher() {
200 return NewLargeFetcher(1);
201 }
202
203 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) = 0;
204 HttpFetcher* NewSmallFetcher() {
205 return NewSmallFetcher(1);
206 }
207
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700208 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
209 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
210 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800211
212 virtual bool IsMock() const = 0;
213 virtual bool IsMulti() const = 0;
214
215 virtual void IgnoreServerAborting(HttpServer* server) const {}
216
217 virtual HttpServer *CreateServer() = 0;
218
219 protected:
220 DirectProxyResolver proxy_resolver_;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700221 FakeSystemState fake_system_state_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800222};
223
224class MockHttpFetcherTest : public AnyHttpFetcherTest {
225 public:
226 // Necessary to unhide the definition in the base class.
227 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800228 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800229 chromeos::Blob big_data(1000000);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700230 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800231 proxy_resolver_.set_num_proxies(num_proxies);
232 return new MockHttpFetcher(
233 big_data.data(),
234 big_data.size(),
235 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
236 }
237
238 // Necessary to unhide the definition in the base class.
239 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800240 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700241 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800242 proxy_resolver_.set_num_proxies(num_proxies);
243 return new MockHttpFetcher(
244 "x",
245 1,
246 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
247 }
248
Alex Deymo610277e2014-11-11 21:18:11 -0800249 bool IsMock() const override { return true; }
250 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800251
Alex Deymo610277e2014-11-11 21:18:11 -0800252 HttpServer *CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800253 return new NullHttpServer;
254 }
255};
256
257class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
258 public:
259 // Necessary to unhide the definition in the base class.
260 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800261 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700262 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800263 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes45168102010-11-22 11:13:50 -0800264 LibcurlHttpFetcher *ret = new
Jay Srinivasan08fce042012-06-07 16:31:01 -0700265 LibcurlHttpFetcher(reinterpret_cast<ProxyResolver*>(&proxy_resolver_),
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700266 &fake_system_state_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700267 // Speed up test execution.
268 ret->set_idle_seconds(1);
269 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700270 fake_system_state_.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 Deymo610277e2014-11-11 21:18:11 -0800276 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800277 return NewLargeFetcher(num_proxies);
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 Deymo610277e2014-11-11 21:18:11 -0800299 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 Deymo610277e2014-11-11 21:18:11 -0800308 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700309 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800310 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800311 ProxyResolver* resolver =
312 reinterpret_cast<ProxyResolver*>(&proxy_resolver_);
Gilad Arnold7c04e762012-05-23 10:54:02 -0700313 MultiRangeHttpFetcher *ret =
314 new MultiRangeHttpFetcher(
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700315 new LibcurlHttpFetcher(resolver, &fake_system_state_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800316 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800317 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700318 // Speed up test execution.
319 ret->set_idle_seconds(1);
320 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700321 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700322 return ret;
323 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800324
325 // Necessary to unhide the definition in the base class.
326 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800327 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800328 return NewLargeFetcher(num_proxies);
329 }
330
Alex Deymo610277e2014-11-11 21:18:11 -0800331 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700332};
333
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800334
335//
336// Infrastructure for type tests of HTTP fetcher.
337// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
338//
339
340// Fixture class template. We use an explicit constraint to guarantee that it
341// can only be instantiated with an AnyHttpFetcherTest type, see:
342// http://www2.research.att.com/~bs/bs_faq2.html#constraints
343template <typename T>
344class HttpFetcherTest : public ::testing::Test {
345 public:
346 T test_;
347
348 private:
349 static void TypeConstraint(T *a) {
350 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700351 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700352 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800353 }
354};
355
356// Test case types list.
357typedef ::testing::Types<LibcurlHttpFetcherTest,
358 MockHttpFetcherTest,
359 MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000360TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
361
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800362
rspangler@google.com49fdf182009-10-10 00:57:34 +0000363namespace {
364class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000365 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800366 HttpFetcherTestDelegate() :
Gilad Arnold48085ba2011-11-16 09:36:08 -0800367 is_expect_error_(false), times_transfer_complete_called_(0),
368 times_transfer_terminated_called_(0), times_received_bytes_called_(0) {}
369
Alex Deymo610277e2014-11-11 21:18:11 -0800370 void ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800371 const void* /* bytes */, size_t /* length */) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800372 // Update counters
373 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000374 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800375
Alex Deymo610277e2014-11-11 21:18:11 -0800376 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800377 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800378 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800379 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800380 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000381 g_main_loop_quit(loop_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800382
383 // Update counter
384 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000385 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800386
Alex Deymo610277e2014-11-11 21:18:11 -0800387 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800388 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800389 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800390 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800391
rspangler@google.com49fdf182009-10-10 00:57:34 +0000392 GMainLoop* loop_;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800393
394 // Are we expecting an error response? (default: no)
395 bool is_expect_error_;
396
397 // Counters for callback invocations.
398 int times_transfer_complete_called_;
399 int times_transfer_terminated_called_;
400 int times_received_bytes_called_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000401};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000402
403struct StartTransferArgs {
404 HttpFetcher *http_fetcher;
405 string url;
406};
407
408gboolean StartTransfer(gpointer data) {
409 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
410 args->http_fetcher->BeginTransfer(args->url);
411 return FALSE;
412}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700413} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000414
415TYPED_TEST(HttpFetcherTest, SimpleTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700416 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000417 {
418 HttpFetcherTestDelegate delegate;
419 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700420 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000421 fetcher->set_delegate(&delegate);
422
Ben Chan02f7c1d2014-10-18 15:18:02 -0700423 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800424 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000425
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700426 StartTransferArgs start_xfer_args = {
427 fetcher.get(), this->test_.SmallUrl(server->GetPort())};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000428
429 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000430 g_main_loop_run(loop);
431 }
432 g_main_loop_unref(loop);
433}
434
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700435TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700436 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700437 {
438 HttpFetcherTestDelegate delegate;
439 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700440 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700441 fetcher->set_delegate(&delegate);
442
Ben Chan02f7c1d2014-10-18 15:18:02 -0700443 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800444 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700445
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700446 StartTransferArgs start_xfer_args = {
447 fetcher.get(), this->test_.BigUrl(server->GetPort())};
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700448
449 g_timeout_add(0, StartTransfer, &start_xfer_args);
450 g_main_loop_run(loop);
451 }
452 g_main_loop_unref(loop);
453}
454
Gilad Arnold48085ba2011-11-16 09:36:08 -0800455// Issue #9648: when server returns an error HTTP response, the fetcher needs to
456// terminate transfer prematurely, rather than try to process the error payload.
457TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800458 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800459 return;
460 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
461 {
462 HttpFetcherTestDelegate delegate;
463 delegate.loop_ = loop;
464
465 // Delegate should expect an error response.
466 delegate.is_expect_error_ = true;
467
Ben Chan02f7c1d2014-10-18 15:18:02 -0700468 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800469 fetcher->set_delegate(&delegate);
470
Ben Chan02f7c1d2014-10-18 15:18:02 -0700471 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800472 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800473
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800474 StartTransferArgs start_xfer_args = {
475 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700476 this->test_.ErrorUrl(server->GetPort())
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800477 };
Gilad Arnold48085ba2011-11-16 09:36:08 -0800478
479 g_timeout_add(0, StartTransfer, &start_xfer_args);
480 g_main_loop_run(loop);
481
482 // Make sure that no bytes were received.
483 CHECK_EQ(delegate.times_received_bytes_called_, 0);
Mike Frysinger0f9547d2012-02-16 12:11:37 -0500484 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800485
486 // Make sure that transfer completion was signaled once, and no termination
487 // was signaled.
488 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
489 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
490 }
491 g_main_loop_unref(loop);
492}
493
rspangler@google.com49fdf182009-10-10 00:57:34 +0000494namespace {
495class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
496 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800497 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800498 const void* /* bytes */, size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000499 CHECK(!paused_);
500 paused_ = true;
501 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000502 }
Alex Deymo610277e2014-11-11 21:18:11 -0800503 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000504 g_main_loop_quit(loop_);
505 }
Alex Deymo610277e2014-11-11 21:18:11 -0800506 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800507 ADD_FAILURE();
508 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000509 void Unpause() {
510 CHECK(paused_);
511 paused_ = false;
512 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000513 }
514 bool paused_;
515 HttpFetcher* fetcher_;
516 GMainLoop* loop_;
517};
518
519gboolean UnpausingTimeoutCallback(gpointer data) {
520 PausingHttpFetcherTestDelegate *delegate =
521 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
522 if (delegate->paused_)
523 delegate->Unpause();
524 return TRUE;
525}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700526} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000527
528TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700529 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000530 {
531 PausingHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700532 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000533 delegate.paused_ = false;
534 delegate.loop_ = loop;
535 delegate.fetcher_ = fetcher.get();
536 fetcher->set_delegate(&delegate);
537
Ben Chan02f7c1d2014-10-18 15:18:02 -0700538 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800539 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800540
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800541 guint callback_id = g_timeout_add(kHttpResponseInternalServerError,
542 UnpausingTimeoutCallback, &delegate);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700543 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000544
545 g_main_loop_run(loop);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800546 g_source_remove(callback_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000547 }
548 g_main_loop_unref(loop);
549}
550
551namespace {
552class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
553 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800554 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800555 const void* bytes, size_t length) override {}
Alex Deymo610277e2014-11-11 21:18:11 -0800556 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800557 ADD_FAILURE(); // We should never get here
rspangler@google.com49fdf182009-10-10 00:57:34 +0000558 g_main_loop_quit(loop_);
559 }
Alex Deymo610277e2014-11-11 21:18:11 -0800560 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800561 EXPECT_EQ(fetcher, fetcher_.get());
562 EXPECT_FALSE(once_);
563 EXPECT_TRUE(callback_once_);
564 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700565 // The fetcher could have a callback scheduled on the ProxyResolver that
566 // can fire after this callback. We wait until the end of the test to
567 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800568 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000569 void TerminateTransfer() {
570 CHECK(once_);
571 once_ = false;
572 fetcher_->TerminateTransfer();
573 }
574 void EndLoop() {
575 g_main_loop_quit(loop_);
576 }
577 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800578 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700579 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000580 GMainLoop* loop_;
581};
582
583gboolean AbortingTimeoutCallback(gpointer data) {
584 AbortingHttpFetcherTestDelegate *delegate =
585 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
586 if (delegate->once_) {
587 delegate->TerminateTransfer();
588 return TRUE;
589 } else {
590 delegate->EndLoop();
591 return FALSE;
592 }
593}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700594} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000595
596TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700597 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000598 {
599 AbortingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800600 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000601 delegate.once_ = true;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800602 delegate.callback_once_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000603 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800604 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000605
Ben Chan02f7c1d2014-10-18 15:18:02 -0700606 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800607 this->test_.IgnoreServerAborting(server.get());
608 ASSERT_TRUE(server->started_);
609
rspangler@google.com49fdf182009-10-10 00:57:34 +0000610 GSource* timeout_source_;
611 timeout_source_ = g_timeout_source_new(0); // ms
612 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700613 nullptr);
614 g_source_attach(timeout_source_, nullptr);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700615 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000616
617 g_main_loop_run(loop);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800618 CHECK(!delegate.once_);
619 CHECK(!delegate.callback_once_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000620 g_source_destroy(timeout_source_);
621 }
622 g_main_loop_unref(loop);
623}
624
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000625namespace {
626class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
627 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800628 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800629 const void* bytes, size_t length) override {
630 data.append(reinterpret_cast<const char*>(bytes), length);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000631 }
Alex Deymo610277e2014-11-11 21:18:11 -0800632 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700633 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800634 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000635 g_main_loop_quit(loop_);
636 }
Alex Deymo610277e2014-11-11 21:18:11 -0800637 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800638 ADD_FAILURE();
639 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000640 string data;
641 GMainLoop* loop_;
642};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700643} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000644
645TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800646 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000647 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700648 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000649 {
650 FlakyHttpFetcherTestDelegate delegate;
651 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700652 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000653 fetcher->set_delegate(&delegate);
654
Ben Chan02f7c1d2014-10-18 15:18:02 -0700655 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800656 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000657
658 StartTransferArgs start_xfer_args = {
659 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700660 LocalServerUrlForPath(server->GetPort(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700661 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
662 kFlakyTruncateLength,
663 kFlakySleepEvery,
664 kFlakySleepSecs))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000665 };
666
667 g_timeout_add(0, StartTransfer, &start_xfer_args);
668 g_main_loop_run(loop);
669
670 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800671 ASSERT_EQ(kBigLength, delegate.data.size());
672 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000673 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
674 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
675 }
676 }
677 g_main_loop_unref(loop);
678}
679
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700680namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700681// This delegate kills the server attached to it after receiving any bytes.
682// This can be used for testing what happens when you try to fetch data and
683// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700684class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
685 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700686 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700687 : loop_(nullptr),
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700688 server_(server) {}
689
Alex Deymo610277e2014-11-11 21:18:11 -0800690 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700691 if (server_) {
692 LOG(INFO) << "Stopping server in destructor";
693 delete server_;
694 LOG(INFO) << "server stopped";
695 }
696 }
697
Alex Deymo610277e2014-11-11 21:18:11 -0800698 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800699 const void* bytes, size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700700 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700701 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700702 delete server_;
703 LOG(INFO) << "server stopped";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700704 server_ = nullptr;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700705 }
706 }
Alex Deymo610277e2014-11-11 21:18:11 -0800707 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700708 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700709 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700710 g_main_loop_quit(loop_);
711 }
Alex Deymo610277e2014-11-11 21:18:11 -0800712 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800713 ADD_FAILURE();
714 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700715 GMainLoop* loop_;
716 PythonHttpServer* server_;
717};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700718} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700719
720
721TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700722 // This test ensures that a fetcher responds correctly when a server isn't
723 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800724 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700725 return;
726 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
727 {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700728 FailureHttpFetcherTestDelegate delegate(nullptr);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700729 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700730 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700731 fetcher->set_delegate(&delegate);
732
733 StartTransferArgs start_xfer_args = {
734 fetcher.get(),
Chris Sosa0a364bb2014-06-10 18:18:24 -0700735 "http://host_doesnt_exist99999999",
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700736 };
737
738 g_timeout_add(0, StartTransfer, &start_xfer_args);
739 g_main_loop_run(loop);
740
741 // Exiting and testing happens in the delegate
742 }
743 g_main_loop_unref(loop);
744}
745
746TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700747 // This test starts a new http server and kills it after receiving its first
748 // set of bytes. It test whether or not our fetcher eventually gives up on
749 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800750 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700751 return;
752 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
753 {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700754 PythonHttpServer* server = new PythonHttpServer();
755 int port = server->GetPort();
756 ASSERT_TRUE(server->started_);
757
758 // Handles destruction and claims ownership.
759 FailureHttpFetcherTestDelegate delegate(server);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700760 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700761 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700762 fetcher->set_delegate(&delegate);
763
764 StartTransferArgs start_xfer_args = {
765 fetcher.get(),
Chris Sosa0a364bb2014-06-10 18:18:24 -0700766 LocalServerUrlForPath(port,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700767 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
768 kFlakyTruncateLength,
769 kFlakySleepEvery,
770 kFlakySleepSecs))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700771 };
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700772 g_timeout_add(0, StartTransfer, &start_xfer_args);
773 g_main_loop_run(loop);
774
775 // Exiting and testing happens in the delegate
776 }
777 g_main_loop_unref(loop);
778}
779
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700780namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800781const HttpResponseCode kRedirectCodes[] = {
782 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
783 kHttpResponseTempRedirect
784};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700785
786class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
787 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700788 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700789 : expected_successful_(expected_successful) {}
Alex Deymo610277e2014-11-11 21:18:11 -0800790 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800791 const void* bytes, size_t length) override {
792 data.append(reinterpret_cast<const char*>(bytes), length);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700793 }
Alex Deymo610277e2014-11-11 21:18:11 -0800794 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700795 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700796 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800797 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700798 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800799 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
800 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700801 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700802 g_main_loop_quit(loop_);
803 }
Alex Deymo610277e2014-11-11 21:18:11 -0800804 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800805 ADD_FAILURE();
806 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700807 bool expected_successful_;
808 string data;
809 GMainLoop* loop_;
810};
811
812// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700813void RedirectTest(const HttpServer* server,
814 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700815 const string& url,
816 HttpFetcher* http_fetcher) {
817 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700818 {
819 RedirectHttpFetcherTestDelegate delegate(expected_successful);
820 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700821 unique_ptr<HttpFetcher> fetcher(http_fetcher);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700822 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700823
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700824 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700825 { fetcher.get(), LocalServerUrlForPath(server->GetPort(), url) };
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700826
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700827 g_timeout_add(0, StartTransfer, &start_xfer_args);
828 g_main_loop_run(loop);
829 if (expected_successful) {
830 // verify the data we get back
831 ASSERT_EQ(kMediumLength, delegate.data.size());
832 for (int i = 0; i < kMediumLength; i += 10) {
833 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
834 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
835 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700836 }
837 }
838 g_main_loop_unref(loop);
839}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700840} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700841
842TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800843 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700844 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800845
Ben Chan02f7c1d2014-10-18 15:18:02 -0700846 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800847 ASSERT_TRUE(server->started_);
848
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700849 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800850 const string url = base::StringPrintf("/redirect/%d/download/%d",
851 kRedirectCodes[c],
852 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700853 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700854 }
855}
856
857TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800858 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700859 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800860
Ben Chan02f7c1d2014-10-18 15:18:02 -0700861 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800862 ASSERT_TRUE(server->started_);
863
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700864 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700865 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700866 url += base::StringPrintf("/redirect/%d",
867 kRedirectCodes[r % arraysize(kRedirectCodes)]);
868 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800869 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700870 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700871}
872
873TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800874 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700875 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800876
Ben Chan02f7c1d2014-10-18 15:18:02 -0700877 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800878 ASSERT_TRUE(server->started_);
879
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700880 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700881 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700882 url += base::StringPrintf("/redirect/%d",
883 kRedirectCodes[r % arraysize(kRedirectCodes)]);
884 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800885 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700886 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700887}
888
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700889namespace {
890class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
891 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700892 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700893 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800894
Alex Deymo610277e2014-11-11 21:18:11 -0800895 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800896 const void* bytes, size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800897 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800898 data.append(reinterpret_cast<const char*>(bytes), length);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700899 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800900
Alex Deymo610277e2014-11-11 21:18:11 -0800901 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800902 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800903 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700904 if (expected_response_code_ != 0)
905 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800906 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700907 fetcher_.reset(nullptr);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700908 g_main_loop_quit(loop_);
909 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800910
Alex Deymo610277e2014-11-11 21:18:11 -0800911 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800912 ADD_FAILURE();
913 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800914
Ben Chan02f7c1d2014-10-18 15:18:02 -0700915 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700916 int expected_response_code_;
917 string data;
918 GMainLoop* loop_;
919};
920
921void MultiTest(HttpFetcher* fetcher_in,
922 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -0700923 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700924 const string& expected_prefix,
925 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800926 HttpResponseCode expected_response_code) {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700927 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
928 {
929 MultiHttpFetcherTestDelegate delegate(expected_response_code);
930 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800931 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -0700932
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800933 MultiRangeHttpFetcher* multi_fetcher =
934 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700935 ASSERT_TRUE(multi_fetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800936 multi_fetcher->ClearRanges();
Ben Chanf9cb98c2014-09-21 18:31:30 -0700937 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800938 e = ranges.end(); it != e; ++it) {
Alex Deymof329b932014-10-30 01:37:48 -0700939 string tmp_str = base::StringPrintf("%jd+", it->first);
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800940 if (it->second > 0) {
941 base::StringAppendF(&tmp_str, "%jd", it->second);
942 multi_fetcher->AddRange(it->first, it->second);
943 } else {
944 base::StringAppendF(&tmp_str, "?");
945 multi_fetcher->AddRange(it->first);
946 }
947 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800948 }
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700949 dynamic_cast<FakeSystemState*>(fetcher_in->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -0700950 ->fake_hardware()->SetIsOfficialBuild(false);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800951 multi_fetcher->set_delegate(&delegate);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700952
Darin Petkov9ce452b2010-11-17 14:33:28 -0800953 StartTransferArgs start_xfer_args = {multi_fetcher, url};
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700954
955 g_timeout_add(0, StartTransfer, &start_xfer_args);
956 g_main_loop_run(loop);
957
958 EXPECT_EQ(expected_size, delegate.data.size());
959 EXPECT_EQ(expected_prefix,
960 string(delegate.data.data(), expected_prefix.size()));
961 }
962 g_main_loop_unref(loop);
963}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700964} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700965
Darin Petkov9ce452b2010-11-17 14:33:28 -0800966TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800967 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700968 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800969
Ben Chan02f7c1d2014-10-18 15:18:02 -0700970 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800971 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700972
Ben Chanf9cb98c2014-09-21 18:31:30 -0700973 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700974 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800975 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800976 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700977 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700978 ranges,
979 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800980 kBigLength - (99 - 25),
981 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700982}
983
984TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800985 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700986 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800987
Ben Chan02f7c1d2014-10-18 15:18:02 -0700988 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800989 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700990
Ben Chanf9cb98c2014-09-21 18:31:30 -0700991 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700992 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800993 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700994 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700995 ranges,
996 "abcdefghijabcdefghijabcd",
997 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800998 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700999}
1000
1001TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001002 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001003 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001004
Ben Chan02f7c1d2014-10-18 15:18:02 -07001005 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001006 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001007
Ben Chanf9cb98c2014-09-21 18:31:30 -07001008 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001009 ranges.push_back(make_pair(kBigLength - 2, 0));
1010 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001011 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001012 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001013 ranges,
1014 "ijhij",
1015 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001016 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001017}
1018
1019TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001020 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001021 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001022
Ben Chan02f7c1d2014-10-18 15:18:02 -07001023 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001024 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001025
Ben Chanf9cb98c2014-09-21 18:31:30 -07001026 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001027 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001028 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001029 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001030 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001031 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001032 ranges,
1033 "ij",
1034 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001035 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001036 ranges.push_back(make_pair(0, 5));
1037 }
1038}
1039
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001040// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1041// should retry with other proxies listed before giving up.
1042//
1043// (1) successful recovery: The offset fetch will fail twice but succeed with
1044// the third proxy.
1045TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1046 if (!this->test_.IsMulti())
1047 return;
1048
Ben Chan02f7c1d2014-10-18 15:18:02 -07001049 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001050 ASSERT_TRUE(server->started_);
1051
Ben Chanf9cb98c2014-09-21 18:31:30 -07001052 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001053 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001054 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001055 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001056 LocalServerUrlForPath(server->GetPort(),
1057 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001058 kBigLength)),
1059 ranges,
1060 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1061 kBigLength - (99 - 25),
1062 kHttpResponsePartialContent);
1063}
1064
1065// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1066// fetcher will signal a (failed) completed transfer to the delegate.
1067TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1068 if (!this->test_.IsMulti())
1069 return;
1070
Ben Chan02f7c1d2014-10-18 15:18:02 -07001071 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001072 ASSERT_TRUE(server->started_);
1073
Ben Chanf9cb98c2014-09-21 18:31:30 -07001074 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001075 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001076 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001077 MultiTest(this->test_.NewLargeFetcher(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001078 LocalServerUrlForPath(server->GetPort(),
1079 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001080 kBigLength)),
1081 ranges,
1082 "abcdefghijabcdefghijabcde", // only received the first chunk
1083 25,
1084 kHttpResponseUndefined);
1085}
1086
1087
1088
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001089namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001090class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001091 public:
Alex Deymo610277e2014-11-11 21:18:11 -08001092 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001093 const void* bytes, size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001094 ADD_FAILURE();
1095 }
Alex Deymo610277e2014-11-11 21:18:11 -08001096 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001097 EXPECT_FALSE(successful);
1098 g_main_loop_quit(loop_);
1099 }
Alex Deymo610277e2014-11-11 21:18:11 -08001100 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001101 ADD_FAILURE();
1102 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001103 GMainLoop* loop_;
1104};
1105
1106} // namespace
1107
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001108TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001109 if (this->test_.IsMock() || this->test_.IsMulti())
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001110 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001111
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001112 for (int i = 0; i < 2; i++) {
Ben Chan02f7c1d2014-10-18 15:18:02 -07001113 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001114 ASSERT_TRUE(server->started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001115
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001116 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001117 {
1118 BlockedTransferTestDelegate delegate;
1119 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001120
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001121 bool is_allowed = (i != 0);
Ben Chan02f7c1d2014-10-18 15:18:02 -07001122 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Jay Srinivasan43488792012-06-19 00:25:31 -07001123
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001124 bool is_official_build = (i == 1);
1125 LOG(INFO) << "is_update_allowed_over_connection: " << is_allowed;
1126 LOG(INFO) << "is_official_build: " << is_official_build;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001127 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
1128 dynamic_cast<FakeSystemState*>(fetcher->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -07001129 ->fake_hardware()->SetIsOfficialBuild(is_official_build);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001130 fetcher->set_delegate(&delegate);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001131
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001132 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001133 {fetcher.get(),
1134 LocalServerUrlForPath(server->GetPort(),
1135 this->test_.SmallUrl(server->GetPort()))};
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001136
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001137 g_timeout_add(0, StartTransfer, &start_xfer_args);
1138 g_main_loop_run(loop);
1139 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001140 g_main_loop_unref(loop);
1141 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001142}
1143
rspangler@google.com49fdf182009-10-10 00:57:34 +00001144} // namespace chromeos_update_engine