blob: 119c3d966f8822816ff72edd906c1351f2ab4cf9 [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) {
Alex Deymo18f48aa2015-04-09 10:06:31 -0700116 PLOG(ERROR) << "error reading http server stdout";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700117 } else {
118 LOG(ERROR) << "server output too short";
119 }
120 Terminate(true);
121 return;
122 }
123
124 line[line_len] = '\0';
125 CHECK_EQ(strstr(line, kServerListeningMsgPrefix), line);
126 const char* listening_port_str = line + listening_msg_prefix_len;
127 char* end_ptr;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700128 long raw_port = strtol(listening_port_str, // NOLINT(runtime/int)
129 &end_ptr, 10);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700130 CHECK(!*end_ptr || *end_ptr == '\n');
131 port_ = static_cast<in_port_t>(raw_port);
132 CHECK_GT(port_, 0);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700133 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700134 LOG(INFO) << "server running, listening on port " << port_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700135 LOG(INFO) << "gdb attach now!";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000136 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800137
rspangler@google.com49fdf182009-10-10 00:57:34 +0000138 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700139 // If there's no process, do nothing.
140 if (pid_ == -1)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000141 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700142
143 // If server is responsive, request that it gracefully terminate.
144 bool do_kill = false;
145 if (started_) {
146 LOG(INFO) << "running wget to exit";
147 if (system((string("wget -t 1 --output-document=/dev/null ") +
148 LocalServerUrlForPath(port_, "/quitquitquit")).c_str())) {
149 LOG(WARNING) << "wget failed, resorting to brute force";
150 do_kill = true;
151 }
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700152 }
153
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700154 // Server not responding or wget failed, kill the process.
155 Terminate(do_kill);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000156 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800157
Alex Deymo610277e2014-11-11 21:18:11 -0800158 in_port_t GetPort() const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700159 return port_;
160 }
161
162 private:
163 void Terminate(bool do_kill) {
164 ASSERT_GT(pid_, 0);
165
166 if (do_kill) {
167 LOG(INFO) << "terminating (SIGKILL) server process with pid " << pid_;
168 kill(pid_, SIGKILL);
169 }
170
171 LOG(INFO) << "waiting for http server with pid " << pid_ << " to terminate";
172 int status;
173 pid_t killed_pid = waitpid(pid_, &status, 0);
174 ASSERT_EQ(killed_pid, pid_);
175 LOG(INFO) << "http server with pid " << pid_
176 << " terminated with status " << status;
177 pid_ = -1;
178 }
179
180 static const char* kServerListeningMsgPrefix;
181
rspangler@google.com49fdf182009-10-10 00:57:34 +0000182 GPid pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700183 in_port_t port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000184};
185
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700186const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
187
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800188//
189// Class hierarchy for HTTP fetcher test wrappers.
190//
191
192class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000193 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700194 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700195 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700196
Alex Deymo7984bf02014-04-02 20:41:57 -0700197 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800198 HttpFetcher* NewLargeFetcher() {
199 return NewLargeFetcher(1);
200 }
201
202 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) = 0;
203 HttpFetcher* NewSmallFetcher() {
204 return NewSmallFetcher(1);
205 }
206
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700207 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
208 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
209 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800210
211 virtual bool IsMock() const = 0;
212 virtual bool IsMulti() const = 0;
213
214 virtual void IgnoreServerAborting(HttpServer* server) const {}
215
216 virtual HttpServer *CreateServer() = 0;
217
218 protected:
219 DirectProxyResolver proxy_resolver_;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700220 FakeSystemState fake_system_state_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800221};
222
223class MockHttpFetcherTest : public AnyHttpFetcherTest {
224 public:
225 // Necessary to unhide the definition in the base class.
226 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800227 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800228 chromeos::Blob big_data(1000000);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700229 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800230 proxy_resolver_.set_num_proxies(num_proxies);
231 return new MockHttpFetcher(
232 big_data.data(),
233 big_data.size(),
234 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
235 }
236
237 // Necessary to unhide the definition in the base class.
238 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800239 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700240 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800241 proxy_resolver_.set_num_proxies(num_proxies);
242 return new MockHttpFetcher(
243 "x",
244 1,
245 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
246 }
247
Alex Deymo610277e2014-11-11 21:18:11 -0800248 bool IsMock() const override { return true; }
249 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800250
Alex Deymo610277e2014-11-11 21:18:11 -0800251 HttpServer *CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800252 return new NullHttpServer;
253 }
254};
255
256class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
257 public:
258 // Necessary to unhide the definition in the base class.
259 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800260 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700261 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800262 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes45168102010-11-22 11:13:50 -0800263 LibcurlHttpFetcher *ret = new
Jay Srinivasan08fce042012-06-07 16:31:01 -0700264 LibcurlHttpFetcher(reinterpret_cast<ProxyResolver*>(&proxy_resolver_),
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700265 &fake_system_state_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700266 // Speed up test execution.
267 ret->set_idle_seconds(1);
268 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700269 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000270 return ret;
271 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800272
273 // Necessary to unhide the definition in the base class.
274 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800275 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800276 return NewLargeFetcher(num_proxies);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000277 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800278
Alex Deymo610277e2014-11-11 21:18:11 -0800279 string BigUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700280 return LocalServerUrlForPath(port,
281 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800282 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000283 }
Alex Deymo610277e2014-11-11 21:18:11 -0800284 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700285 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000286 }
Alex Deymo610277e2014-11-11 21:18:11 -0800287 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700288 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800289 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800290
Alex Deymo610277e2014-11-11 21:18:11 -0800291 bool IsMock() const override { return false; }
292 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800293
Alex Deymo610277e2014-11-11 21:18:11 -0800294 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700295 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700296 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800297
Alex Deymo610277e2014-11-11 21:18:11 -0800298 HttpServer *CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800299 return new PythonHttpServer;
300 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000301};
302
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800303class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700304 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800305 // Necessary to unhide the definition in the base class.
306 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800307 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700308 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800309 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800310 ProxyResolver* resolver =
311 reinterpret_cast<ProxyResolver*>(&proxy_resolver_);
Gilad Arnold7c04e762012-05-23 10:54:02 -0700312 MultiRangeHttpFetcher *ret =
313 new MultiRangeHttpFetcher(
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700314 new LibcurlHttpFetcher(resolver, &fake_system_state_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800315 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800316 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700317 // Speed up test execution.
318 ret->set_idle_seconds(1);
319 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700320 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700321 return ret;
322 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800323
324 // Necessary to unhide the definition in the base class.
325 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800326 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800327 return NewLargeFetcher(num_proxies);
328 }
329
Alex Deymo610277e2014-11-11 21:18:11 -0800330 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700331};
332
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800333
334//
335// Infrastructure for type tests of HTTP fetcher.
336// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
337//
338
339// Fixture class template. We use an explicit constraint to guarantee that it
340// can only be instantiated with an AnyHttpFetcherTest type, see:
341// http://www2.research.att.com/~bs/bs_faq2.html#constraints
342template <typename T>
343class HttpFetcherTest : public ::testing::Test {
344 public:
345 T test_;
346
347 private:
348 static void TypeConstraint(T *a) {
349 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700350 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700351 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800352 }
353};
354
355// Test case types list.
356typedef ::testing::Types<LibcurlHttpFetcherTest,
357 MockHttpFetcherTest,
358 MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000359TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
360
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800361
rspangler@google.com49fdf182009-10-10 00:57:34 +0000362namespace {
363class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000364 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800365 HttpFetcherTestDelegate() :
Gilad Arnold48085ba2011-11-16 09:36:08 -0800366 is_expect_error_(false), times_transfer_complete_called_(0),
367 times_transfer_terminated_called_(0), times_received_bytes_called_(0) {}
368
Alex Deymo610277e2014-11-11 21:18:11 -0800369 void ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800370 const void* /* bytes */, size_t /* length */) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800371 // Update counters
372 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000373 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800374
Alex Deymo610277e2014-11-11 21:18:11 -0800375 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800376 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800377 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800378 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800379 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000380 g_main_loop_quit(loop_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800381
382 // Update counter
383 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000384 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800385
Alex Deymo610277e2014-11-11 21:18:11 -0800386 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800387 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800388 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800389 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800390
rspangler@google.com49fdf182009-10-10 00:57:34 +0000391 GMainLoop* loop_;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800392
393 // Are we expecting an error response? (default: no)
394 bool is_expect_error_;
395
396 // Counters for callback invocations.
397 int times_transfer_complete_called_;
398 int times_transfer_terminated_called_;
399 int times_received_bytes_called_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000400};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000401
402struct StartTransferArgs {
403 HttpFetcher *http_fetcher;
404 string url;
405};
406
407gboolean StartTransfer(gpointer data) {
408 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
409 args->http_fetcher->BeginTransfer(args->url);
410 return FALSE;
411}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700412} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000413
414TYPED_TEST(HttpFetcherTest, SimpleTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700415 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000416 {
417 HttpFetcherTestDelegate delegate;
418 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700419 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000420 fetcher->set_delegate(&delegate);
421
Ben Chan02f7c1d2014-10-18 15:18:02 -0700422 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800423 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000424
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700425 StartTransferArgs start_xfer_args = {
426 fetcher.get(), this->test_.SmallUrl(server->GetPort())};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000427
428 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000429 g_main_loop_run(loop);
430 }
431 g_main_loop_unref(loop);
432}
433
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700434TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700435 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700436 {
437 HttpFetcherTestDelegate delegate;
438 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700439 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700440 fetcher->set_delegate(&delegate);
441
Ben Chan02f7c1d2014-10-18 15:18:02 -0700442 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800443 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700444
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700445 StartTransferArgs start_xfer_args = {
446 fetcher.get(), this->test_.BigUrl(server->GetPort())};
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700447
448 g_timeout_add(0, StartTransfer, &start_xfer_args);
449 g_main_loop_run(loop);
450 }
451 g_main_loop_unref(loop);
452}
453
Gilad Arnold48085ba2011-11-16 09:36:08 -0800454// Issue #9648: when server returns an error HTTP response, the fetcher needs to
455// terminate transfer prematurely, rather than try to process the error payload.
456TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800457 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800458 return;
459 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
460 {
461 HttpFetcherTestDelegate delegate;
462 delegate.loop_ = loop;
463
464 // Delegate should expect an error response.
465 delegate.is_expect_error_ = true;
466
Ben Chan02f7c1d2014-10-18 15:18:02 -0700467 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800468 fetcher->set_delegate(&delegate);
469
Ben Chan02f7c1d2014-10-18 15:18:02 -0700470 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800471 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800472
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800473 StartTransferArgs start_xfer_args = {
474 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700475 this->test_.ErrorUrl(server->GetPort())
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800476 };
Gilad Arnold48085ba2011-11-16 09:36:08 -0800477
478 g_timeout_add(0, StartTransfer, &start_xfer_args);
479 g_main_loop_run(loop);
480
481 // Make sure that no bytes were received.
482 CHECK_EQ(delegate.times_received_bytes_called_, 0);
Mike Frysinger0f9547d2012-02-16 12:11:37 -0500483 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800484
485 // Make sure that transfer completion was signaled once, and no termination
486 // was signaled.
487 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
488 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
489 }
490 g_main_loop_unref(loop);
491}
492
rspangler@google.com49fdf182009-10-10 00:57:34 +0000493namespace {
494class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
495 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800496 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800497 const void* /* bytes */, size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000498 CHECK(!paused_);
499 paused_ = true;
500 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000501 }
Alex Deymo610277e2014-11-11 21:18:11 -0800502 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000503 g_main_loop_quit(loop_);
504 }
Alex Deymo610277e2014-11-11 21:18:11 -0800505 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800506 ADD_FAILURE();
507 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000508 void Unpause() {
509 CHECK(paused_);
510 paused_ = false;
511 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000512 }
513 bool paused_;
514 HttpFetcher* fetcher_;
515 GMainLoop* loop_;
516};
517
518gboolean UnpausingTimeoutCallback(gpointer data) {
519 PausingHttpFetcherTestDelegate *delegate =
520 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
521 if (delegate->paused_)
522 delegate->Unpause();
523 return TRUE;
524}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700525} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000526
527TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700528 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000529 {
530 PausingHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700531 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000532 delegate.paused_ = false;
533 delegate.loop_ = loop;
534 delegate.fetcher_ = fetcher.get();
535 fetcher->set_delegate(&delegate);
536
Ben Chan02f7c1d2014-10-18 15:18:02 -0700537 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800538 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800539
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800540 guint callback_id = g_timeout_add(kHttpResponseInternalServerError,
541 UnpausingTimeoutCallback, &delegate);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700542 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000543
544 g_main_loop_run(loop);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800545 g_source_remove(callback_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000546 }
547 g_main_loop_unref(loop);
548}
549
550namespace {
551class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
552 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800553 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800554 const void* bytes, size_t length) override {}
Alex Deymo610277e2014-11-11 21:18:11 -0800555 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800556 ADD_FAILURE(); // We should never get here
rspangler@google.com49fdf182009-10-10 00:57:34 +0000557 g_main_loop_quit(loop_);
558 }
Alex Deymo610277e2014-11-11 21:18:11 -0800559 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800560 EXPECT_EQ(fetcher, fetcher_.get());
561 EXPECT_FALSE(once_);
562 EXPECT_TRUE(callback_once_);
563 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700564 // The fetcher could have a callback scheduled on the ProxyResolver that
565 // can fire after this callback. We wait until the end of the test to
566 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800567 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000568 void TerminateTransfer() {
569 CHECK(once_);
570 once_ = false;
571 fetcher_->TerminateTransfer();
572 }
573 void EndLoop() {
574 g_main_loop_quit(loop_);
575 }
576 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800577 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700578 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000579 GMainLoop* loop_;
580};
581
582gboolean AbortingTimeoutCallback(gpointer data) {
583 AbortingHttpFetcherTestDelegate *delegate =
584 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
585 if (delegate->once_) {
586 delegate->TerminateTransfer();
587 return TRUE;
588 } else {
589 delegate->EndLoop();
590 return FALSE;
591 }
592}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700593} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000594
595TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700596 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000597 {
598 AbortingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800599 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000600 delegate.once_ = true;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800601 delegate.callback_once_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000602 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800603 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000604
Ben Chan02f7c1d2014-10-18 15:18:02 -0700605 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800606 this->test_.IgnoreServerAborting(server.get());
607 ASSERT_TRUE(server->started_);
608
rspangler@google.com49fdf182009-10-10 00:57:34 +0000609 GSource* timeout_source_;
610 timeout_source_ = g_timeout_source_new(0); // ms
611 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700612 nullptr);
613 g_source_attach(timeout_source_, nullptr);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700614 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000615
616 g_main_loop_run(loop);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800617 CHECK(!delegate.once_);
618 CHECK(!delegate.callback_once_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000619 g_source_destroy(timeout_source_);
620 }
621 g_main_loop_unref(loop);
622}
623
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000624namespace {
625class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
626 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800627 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800628 const void* bytes, size_t length) override {
629 data.append(reinterpret_cast<const char*>(bytes), length);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000630 }
Alex Deymo610277e2014-11-11 21:18:11 -0800631 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700632 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800633 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000634 g_main_loop_quit(loop_);
635 }
Alex Deymo610277e2014-11-11 21:18:11 -0800636 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800637 ADD_FAILURE();
638 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000639 string data;
640 GMainLoop* loop_;
641};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700642} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000643
644TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800645 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000646 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700647 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000648 {
649 FlakyHttpFetcherTestDelegate delegate;
650 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700651 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000652 fetcher->set_delegate(&delegate);
653
Ben Chan02f7c1d2014-10-18 15:18:02 -0700654 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800655 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000656
657 StartTransferArgs start_xfer_args = {
658 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700659 LocalServerUrlForPath(server->GetPort(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700660 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
661 kFlakyTruncateLength,
662 kFlakySleepEvery,
663 kFlakySleepSecs))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000664 };
665
666 g_timeout_add(0, StartTransfer, &start_xfer_args);
667 g_main_loop_run(loop);
668
669 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800670 ASSERT_EQ(kBigLength, delegate.data.size());
671 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000672 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
673 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
674 }
675 }
676 g_main_loop_unref(loop);
677}
678
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700679namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700680// This delegate kills the server attached to it after receiving any bytes.
681// This can be used for testing what happens when you try to fetch data and
682// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700683class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
684 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700685 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700686 : loop_(nullptr),
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700687 server_(server) {}
688
Alex Deymo610277e2014-11-11 21:18:11 -0800689 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700690 if (server_) {
691 LOG(INFO) << "Stopping server in destructor";
692 delete server_;
693 LOG(INFO) << "server stopped";
694 }
695 }
696
Alex Deymo610277e2014-11-11 21:18:11 -0800697 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800698 const void* bytes, size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700699 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700700 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700701 delete server_;
702 LOG(INFO) << "server stopped";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700703 server_ = nullptr;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700704 }
705 }
Alex Deymo610277e2014-11-11 21:18:11 -0800706 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700707 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700708 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700709 g_main_loop_quit(loop_);
710 }
Alex Deymo610277e2014-11-11 21:18:11 -0800711 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800712 ADD_FAILURE();
713 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700714 GMainLoop* loop_;
715 PythonHttpServer* server_;
716};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700717} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700718
719
720TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700721 // This test ensures that a fetcher responds correctly when a server isn't
722 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800723 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700724 return;
725 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
726 {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700727 FailureHttpFetcherTestDelegate delegate(nullptr);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700728 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700729 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700730 fetcher->set_delegate(&delegate);
731
732 StartTransferArgs start_xfer_args = {
733 fetcher.get(),
Chris Sosa0a364bb2014-06-10 18:18:24 -0700734 "http://host_doesnt_exist99999999",
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700735 };
736
737 g_timeout_add(0, StartTransfer, &start_xfer_args);
738 g_main_loop_run(loop);
739
740 // Exiting and testing happens in the delegate
741 }
742 g_main_loop_unref(loop);
743}
744
745TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700746 // This test starts a new http server and kills it after receiving its first
747 // set of bytes. It test whether or not our fetcher eventually gives up on
748 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800749 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700750 return;
751 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
752 {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700753 PythonHttpServer* server = new PythonHttpServer();
754 int port = server->GetPort();
755 ASSERT_TRUE(server->started_);
756
757 // Handles destruction and claims ownership.
758 FailureHttpFetcherTestDelegate delegate(server);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700759 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700760 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700761 fetcher->set_delegate(&delegate);
762
763 StartTransferArgs start_xfer_args = {
764 fetcher.get(),
Chris Sosa0a364bb2014-06-10 18:18:24 -0700765 LocalServerUrlForPath(port,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700766 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
767 kFlakyTruncateLength,
768 kFlakySleepEvery,
769 kFlakySleepSecs))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700770 };
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700771 g_timeout_add(0, StartTransfer, &start_xfer_args);
772 g_main_loop_run(loop);
773
774 // Exiting and testing happens in the delegate
775 }
776 g_main_loop_unref(loop);
777}
778
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700779namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800780const HttpResponseCode kRedirectCodes[] = {
781 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
782 kHttpResponseTempRedirect
783};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700784
785class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
786 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700787 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700788 : expected_successful_(expected_successful) {}
Alex Deymo610277e2014-11-11 21:18:11 -0800789 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800790 const void* bytes, size_t length) override {
791 data.append(reinterpret_cast<const char*>(bytes), length);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700792 }
Alex Deymo610277e2014-11-11 21:18:11 -0800793 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700794 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700795 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800796 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700797 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800798 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
799 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700800 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700801 g_main_loop_quit(loop_);
802 }
Alex Deymo610277e2014-11-11 21:18:11 -0800803 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800804 ADD_FAILURE();
805 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700806 bool expected_successful_;
807 string data;
808 GMainLoop* loop_;
809};
810
811// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700812void RedirectTest(const HttpServer* server,
813 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700814 const string& url,
815 HttpFetcher* http_fetcher) {
816 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700817 {
818 RedirectHttpFetcherTestDelegate delegate(expected_successful);
819 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700820 unique_ptr<HttpFetcher> fetcher(http_fetcher);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700821 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700822
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700823 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700824 { fetcher.get(), LocalServerUrlForPath(server->GetPort(), url) };
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700825
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700826 g_timeout_add(0, StartTransfer, &start_xfer_args);
827 g_main_loop_run(loop);
828 if (expected_successful) {
829 // verify the data we get back
830 ASSERT_EQ(kMediumLength, delegate.data.size());
831 for (int i = 0; i < kMediumLength; i += 10) {
832 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
833 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
834 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700835 }
836 }
837 g_main_loop_unref(loop);
838}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700839} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700840
841TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800842 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700843 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800844
Ben Chan02f7c1d2014-10-18 15:18:02 -0700845 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800846 ASSERT_TRUE(server->started_);
847
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700848 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800849 const string url = base::StringPrintf("/redirect/%d/download/%d",
850 kRedirectCodes[c],
851 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700852 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700853 }
854}
855
856TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800857 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700858 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800859
Ben Chan02f7c1d2014-10-18 15:18:02 -0700860 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800861 ASSERT_TRUE(server->started_);
862
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700863 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700864 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700865 url += base::StringPrintf("/redirect/%d",
866 kRedirectCodes[r % arraysize(kRedirectCodes)]);
867 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800868 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700869 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700870}
871
872TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800873 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700874 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800875
Ben Chan02f7c1d2014-10-18 15:18:02 -0700876 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800877 ASSERT_TRUE(server->started_);
878
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700879 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700880 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700881 url += base::StringPrintf("/redirect/%d",
882 kRedirectCodes[r % arraysize(kRedirectCodes)]);
883 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800884 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700885 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700886}
887
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700888namespace {
889class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
890 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700891 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700892 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800893
Alex Deymo610277e2014-11-11 21:18:11 -0800894 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800895 const void* bytes, size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800896 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800897 data.append(reinterpret_cast<const char*>(bytes), length);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700898 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800899
Alex Deymo610277e2014-11-11 21:18:11 -0800900 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800901 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800902 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700903 if (expected_response_code_ != 0)
904 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800905 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700906 fetcher_.reset(nullptr);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700907 g_main_loop_quit(loop_);
908 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800909
Alex Deymo610277e2014-11-11 21:18:11 -0800910 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800911 ADD_FAILURE();
912 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800913
Ben Chan02f7c1d2014-10-18 15:18:02 -0700914 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700915 int expected_response_code_;
916 string data;
917 GMainLoop* loop_;
918};
919
920void MultiTest(HttpFetcher* fetcher_in,
921 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -0700922 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700923 const string& expected_prefix,
924 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800925 HttpResponseCode expected_response_code) {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700926 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
927 {
928 MultiHttpFetcherTestDelegate delegate(expected_response_code);
929 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800930 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -0700931
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800932 MultiRangeHttpFetcher* multi_fetcher =
933 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700934 ASSERT_TRUE(multi_fetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800935 multi_fetcher->ClearRanges();
Ben Chanf9cb98c2014-09-21 18:31:30 -0700936 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800937 e = ranges.end(); it != e; ++it) {
Alex Deymof329b932014-10-30 01:37:48 -0700938 string tmp_str = base::StringPrintf("%jd+", it->first);
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800939 if (it->second > 0) {
940 base::StringAppendF(&tmp_str, "%jd", it->second);
941 multi_fetcher->AddRange(it->first, it->second);
942 } else {
943 base::StringAppendF(&tmp_str, "?");
944 multi_fetcher->AddRange(it->first);
945 }
946 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800947 }
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700948 dynamic_cast<FakeSystemState*>(fetcher_in->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -0700949 ->fake_hardware()->SetIsOfficialBuild(false);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800950 multi_fetcher->set_delegate(&delegate);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700951
Darin Petkov9ce452b2010-11-17 14:33:28 -0800952 StartTransferArgs start_xfer_args = {multi_fetcher, url};
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700953
954 g_timeout_add(0, StartTransfer, &start_xfer_args);
955 g_main_loop_run(loop);
956
957 EXPECT_EQ(expected_size, delegate.data.size());
958 EXPECT_EQ(expected_prefix,
959 string(delegate.data.data(), expected_prefix.size()));
960 }
961 g_main_loop_unref(loop);
962}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700963} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700964
Darin Petkov9ce452b2010-11-17 14:33:28 -0800965TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800966 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700967 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800968
Ben Chan02f7c1d2014-10-18 15:18:02 -0700969 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800970 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700971
Ben Chanf9cb98c2014-09-21 18:31:30 -0700972 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700973 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800974 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800975 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700976 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700977 ranges,
978 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800979 kBigLength - (99 - 25),
980 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700981}
982
983TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800984 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700985 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800986
Ben Chan02f7c1d2014-10-18 15:18:02 -0700987 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800988 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700989
Ben Chanf9cb98c2014-09-21 18:31:30 -0700990 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700991 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800992 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700993 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700994 ranges,
995 "abcdefghijabcdefghijabcd",
996 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800997 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700998}
999
1000TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001001 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001002 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001003
Ben Chan02f7c1d2014-10-18 15:18:02 -07001004 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001005 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001006
Ben Chanf9cb98c2014-09-21 18:31:30 -07001007 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001008 ranges.push_back(make_pair(kBigLength - 2, 0));
1009 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001010 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001011 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001012 ranges,
1013 "ijhij",
1014 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001015 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001016}
1017
1018TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001019 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001020 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001021
Ben Chan02f7c1d2014-10-18 15:18:02 -07001022 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001023 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001024
Ben Chanf9cb98c2014-09-21 18:31:30 -07001025 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001026 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001027 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001028 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001029 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001030 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001031 ranges,
1032 "ij",
1033 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001034 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001035 ranges.push_back(make_pair(0, 5));
1036 }
1037}
1038
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001039// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1040// should retry with other proxies listed before giving up.
1041//
1042// (1) successful recovery: The offset fetch will fail twice but succeed with
1043// the third proxy.
1044TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1045 if (!this->test_.IsMulti())
1046 return;
1047
Ben Chan02f7c1d2014-10-18 15:18:02 -07001048 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001049 ASSERT_TRUE(server->started_);
1050
Ben Chanf9cb98c2014-09-21 18:31:30 -07001051 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001052 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001053 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001054 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001055 LocalServerUrlForPath(server->GetPort(),
1056 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001057 kBigLength)),
1058 ranges,
1059 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1060 kBigLength - (99 - 25),
1061 kHttpResponsePartialContent);
1062}
1063
1064// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1065// fetcher will signal a (failed) completed transfer to the delegate.
1066TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1067 if (!this->test_.IsMulti())
1068 return;
1069
Ben Chan02f7c1d2014-10-18 15:18:02 -07001070 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001071 ASSERT_TRUE(server->started_);
1072
Ben Chanf9cb98c2014-09-21 18:31:30 -07001073 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001074 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001075 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001076 MultiTest(this->test_.NewLargeFetcher(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001077 LocalServerUrlForPath(server->GetPort(),
1078 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001079 kBigLength)),
1080 ranges,
1081 "abcdefghijabcdefghijabcde", // only received the first chunk
1082 25,
1083 kHttpResponseUndefined);
1084}
1085
1086
1087
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001088namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001089class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001090 public:
Alex Deymo610277e2014-11-11 21:18:11 -08001091 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001092 const void* bytes, size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001093 ADD_FAILURE();
1094 }
Alex Deymo610277e2014-11-11 21:18:11 -08001095 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001096 EXPECT_FALSE(successful);
1097 g_main_loop_quit(loop_);
1098 }
Alex Deymo610277e2014-11-11 21:18:11 -08001099 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001100 ADD_FAILURE();
1101 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001102 GMainLoop* loop_;
1103};
1104
1105} // namespace
1106
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001107TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001108 if (this->test_.IsMock() || this->test_.IsMulti())
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001109 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001110
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001111 for (int i = 0; i < 2; i++) {
Ben Chan02f7c1d2014-10-18 15:18:02 -07001112 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001113 ASSERT_TRUE(server->started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001114
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001115 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001116 {
1117 BlockedTransferTestDelegate delegate;
1118 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001119
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001120 bool is_allowed = (i != 0);
Ben Chan02f7c1d2014-10-18 15:18:02 -07001121 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Jay Srinivasan43488792012-06-19 00:25:31 -07001122
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001123 bool is_official_build = (i == 1);
1124 LOG(INFO) << "is_update_allowed_over_connection: " << is_allowed;
1125 LOG(INFO) << "is_official_build: " << is_official_build;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001126 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
1127 dynamic_cast<FakeSystemState*>(fetcher->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -07001128 ->fake_hardware()->SetIsOfficialBuild(is_official_build);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001129 fetcher->set_delegate(&delegate);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001130
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001131 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001132 {fetcher.get(),
1133 LocalServerUrlForPath(server->GetPort(),
1134 this->test_.SmallUrl(server->GetPort()))};
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001135
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001136 g_timeout_add(0, StartTransfer, &start_xfer_args);
1137 g_main_loop_run(loop);
1138 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001139 g_main_loop_unref(loop);
1140 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001141}
1142
rspangler@google.com49fdf182009-10-10 00:57:34 +00001143} // namespace chromeos_update_engine