blob: 3879bc45432c9549807e87167f673b2e2778b3e7 [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
adlr@google.comc98a7ed2009-12-04 18:54:03 +000010#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070011#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000012#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070013
Andrew de los Reyes45168102010-11-22 11:13:50 -080014#include <base/logging.h>
Chris Masoned903c3b2011-05-12 15:35:46 -070015#include <base/memory/scoped_ptr.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;
34using std::vector;
35
Gilad Arnold8e3f1262013-01-08 14:59:54 -080036using base::TimeDelta;
Jay Srinivasan43488792012-06-19 00:25:31 -070037using testing::DoAll;
38using testing::Return;
Alex Deymoc4acdf42014-05-28 21:07:10 -070039using testing::SetArgumentPointee;
40using testing::_;
Jay Srinivasan43488792012-06-19 00:25:31 -070041
Gilad Arnold9bedeb52011-11-17 16:19:57 -080042namespace {
43
44const int kBigLength = 100000;
45const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080046const int kFlakyTruncateLength = 29000;
47const int kFlakySleepEvery = 3;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080048const int kFlakySleepSecs = 10;
49
50} // namespace
51
rspangler@google.com49fdf182009-10-10 00:57:34 +000052namespace chromeos_update_engine {
53
Gilad Arnold9bedeb52011-11-17 16:19:57 -080054static const char *kUnusedUrl = "unused://unused";
55
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070056static inline string LocalServerUrlForPath(in_port_t port,
57 const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070058 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070059 return base::StringPrintf("http://127.0.0.1%s%s", port_str.c_str(),
60 path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000061}
62
Gilad Arnold9bedeb52011-11-17 16:19:57 -080063//
64// Class hierarchy for HTTP server implementations.
65//
66
67class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000068 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080069 // This makes it an abstract class (dirty but works).
70 virtual ~HttpServer() = 0;
71
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070072 virtual in_port_t GetPort() const {
73 return 0;
74 }
75
rspangler@google.com49fdf182009-10-10 00:57:34 +000076 bool started_;
77};
78
Gilad Arnold9bedeb52011-11-17 16:19:57 -080079HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +000080
Gilad Arnold9bedeb52011-11-17 16:19:57 -080081
82class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000083 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080084 NullHttpServer() {
85 started_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +000086 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000087};
88
Gilad Arnold9bedeb52011-11-17 16:19:57 -080089
90class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000091 public:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070092 PythonHttpServer() : pid_(-1), port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000093 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070094
95 // Spawn the server process.
96 gchar *argv[] = {
97 const_cast<gchar*>("./test_http_server"),
98 NULL };
99 GError *err;
100 gint server_stdout = -1;
101 if (!g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
102 NULL, NULL, &pid_, NULL, &server_stdout, NULL,
103 &err)) {
104 LOG(ERROR) << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000105 return;
106 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700107 CHECK_GT(pid_, 0);
108 CHECK_GE(server_stdout, 0);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700109 LOG(INFO) << "started http server with pid " << pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700110
111 // Wait for server to begin accepting connections, obtain its port.
112 char line[80];
113 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
114 CHECK_GT(sizeof(line), listening_msg_prefix_len);
115 int line_len = read(server_stdout, line, sizeof(line) - 1);
116 if (line_len <= static_cast<int>(listening_msg_prefix_len)) {
117 if (line_len < 0) {
118 LOG(ERROR) << "error reading http server stdout: "
119 << strerror(errno);
120 } else {
121 LOG(ERROR) << "server output too short";
122 }
123 Terminate(true);
124 return;
125 }
126
127 line[line_len] = '\0';
128 CHECK_EQ(strstr(line, kServerListeningMsgPrefix), line);
129 const char* listening_port_str = line + listening_msg_prefix_len;
130 char* end_ptr;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700131 long raw_port = strtol(listening_port_str, // NOLINT(runtime/int)
132 &end_ptr, 10);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700133 CHECK(!*end_ptr || *end_ptr == '\n');
134 port_ = static_cast<in_port_t>(raw_port);
135 CHECK_GT(port_, 0);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700136 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700137 LOG(INFO) << "server running, listening on port " << port_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700138 LOG(INFO) << "gdb attach now!";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000139 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800140
rspangler@google.com49fdf182009-10-10 00:57:34 +0000141 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700142 // If there's no process, do nothing.
143 if (pid_ == -1)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000144 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700145
146 // If server is responsive, request that it gracefully terminate.
147 bool do_kill = false;
148 if (started_) {
149 LOG(INFO) << "running wget to exit";
150 if (system((string("wget -t 1 --output-document=/dev/null ") +
151 LocalServerUrlForPath(port_, "/quitquitquit")).c_str())) {
152 LOG(WARNING) << "wget failed, resorting to brute force";
153 do_kill = true;
154 }
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700155 }
156
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700157 // Server not responding or wget failed, kill the process.
158 Terminate(do_kill);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000159 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800160
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700161 virtual in_port_t GetPort() const {
162 return port_;
163 }
164
165 private:
166 void Terminate(bool do_kill) {
167 ASSERT_GT(pid_, 0);
168
169 if (do_kill) {
170 LOG(INFO) << "terminating (SIGKILL) server process with pid " << pid_;
171 kill(pid_, SIGKILL);
172 }
173
174 LOG(INFO) << "waiting for http server with pid " << pid_ << " to terminate";
175 int status;
176 pid_t killed_pid = waitpid(pid_, &status, 0);
177 ASSERT_EQ(killed_pid, pid_);
178 LOG(INFO) << "http server with pid " << pid_
179 << " terminated with status " << status;
180 pid_ = -1;
181 }
182
183 static const char* kServerListeningMsgPrefix;
184
rspangler@google.com49fdf182009-10-10 00:57:34 +0000185 GPid pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700186 in_port_t port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000187};
188
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700189const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
190
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800191//
192// Class hierarchy for HTTP fetcher test wrappers.
193//
194
195class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000196 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700197 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700198 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700199
Alex Deymo7984bf02014-04-02 20:41:57 -0700200 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800201 HttpFetcher* NewLargeFetcher() {
202 return NewLargeFetcher(1);
203 }
204
205 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) = 0;
206 HttpFetcher* NewSmallFetcher() {
207 return NewSmallFetcher(1);
208 }
209
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700210 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
211 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
212 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800213
214 virtual bool IsMock() const = 0;
215 virtual bool IsMulti() const = 0;
216
217 virtual void IgnoreServerAborting(HttpServer* server) const {}
218
219 virtual HttpServer *CreateServer() = 0;
220
221 protected:
222 DirectProxyResolver proxy_resolver_;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700223 FakeSystemState fake_system_state_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800224};
225
226class MockHttpFetcherTest : public AnyHttpFetcherTest {
227 public:
228 // Necessary to unhide the definition in the base class.
229 using AnyHttpFetcherTest::NewLargeFetcher;
230 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) {
231 vector<char> big_data(1000000);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700232 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800233 proxy_resolver_.set_num_proxies(num_proxies);
234 return new MockHttpFetcher(
235 big_data.data(),
236 big_data.size(),
237 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
238 }
239
240 // Necessary to unhide the definition in the base class.
241 using AnyHttpFetcherTest::NewSmallFetcher;
242 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700243 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800244 proxy_resolver_.set_num_proxies(num_proxies);
245 return new MockHttpFetcher(
246 "x",
247 1,
248 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
249 }
250
251 virtual bool IsMock() const { return true; }
252 virtual bool IsMulti() const { return false; }
253
254 virtual HttpServer *CreateServer() {
255 return new NullHttpServer;
256 }
257};
258
259class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
260 public:
261 // Necessary to unhide the definition in the base class.
262 using AnyHttpFetcherTest::NewLargeFetcher;
263 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700264 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800265 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes45168102010-11-22 11:13:50 -0800266 LibcurlHttpFetcher *ret = new
Jay Srinivasan08fce042012-06-07 16:31:01 -0700267 LibcurlHttpFetcher(reinterpret_cast<ProxyResolver*>(&proxy_resolver_),
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700268 &fake_system_state_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700269 // Speed up test execution.
270 ret->set_idle_seconds(1);
271 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700272 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000273 return ret;
274 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800275
276 // Necessary to unhide the definition in the base class.
277 using AnyHttpFetcherTest::NewSmallFetcher;
278 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) {
279 return NewLargeFetcher(num_proxies);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000280 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800281
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700282 virtual string BigUrl(in_port_t port) const {
283 return LocalServerUrlForPath(port,
284 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800285 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000286 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700287 virtual string SmallUrl(in_port_t port) const {
288 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000289 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700290 virtual string ErrorUrl(in_port_t port) const {
291 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800292 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800293
294 virtual bool IsMock() const { return false; }
295 virtual bool IsMulti() const { return false; }
296
297 virtual void IgnoreServerAborting(HttpServer* server) const {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700298 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700299 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800300
301 virtual HttpServer *CreateServer() {
302 return new PythonHttpServer;
303 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000304};
305
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800306class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700307 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800308 // Necessary to unhide the definition in the base class.
309 using AnyHttpFetcherTest::NewLargeFetcher;
310 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700311 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800312 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800313 ProxyResolver* resolver =
314 reinterpret_cast<ProxyResolver*>(&proxy_resolver_);
Gilad Arnold7c04e762012-05-23 10:54:02 -0700315 MultiRangeHttpFetcher *ret =
316 new MultiRangeHttpFetcher(
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700317 new LibcurlHttpFetcher(resolver, &fake_system_state_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800318 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800319 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700320 // Speed up test execution.
321 ret->set_idle_seconds(1);
322 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700323 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700324 return ret;
325 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800326
327 // Necessary to unhide the definition in the base class.
328 using AnyHttpFetcherTest::NewSmallFetcher;
329 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) {
330 return NewLargeFetcher(num_proxies);
331 }
332
333 virtual bool IsMulti() const { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700334};
335
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800336
337//
338// Infrastructure for type tests of HTTP fetcher.
339// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
340//
341
342// Fixture class template. We use an explicit constraint to guarantee that it
343// can only be instantiated with an AnyHttpFetcherTest type, see:
344// http://www2.research.att.com/~bs/bs_faq2.html#constraints
345template <typename T>
346class HttpFetcherTest : public ::testing::Test {
347 public:
348 T test_;
349
350 private:
351 static void TypeConstraint(T *a) {
352 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700353 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700354 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800355 }
356};
357
358// Test case types list.
359typedef ::testing::Types<LibcurlHttpFetcherTest,
360 MockHttpFetcherTest,
361 MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000362TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
363
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800364
rspangler@google.com49fdf182009-10-10 00:57:34 +0000365namespace {
366class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000367 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800368 HttpFetcherTestDelegate() :
Gilad Arnold48085ba2011-11-16 09:36:08 -0800369 is_expect_error_(false), times_transfer_complete_called_(0),
370 times_transfer_terminated_called_(0), times_received_bytes_called_(0) {}
371
Alex Deymof9c59992014-04-02 21:16:59 -0700372 virtual void ReceivedBytes(HttpFetcher* /* fetcher */,
373 const char* /* bytes */, int /* length */) {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800374 // Update counters
375 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000376 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800377
rspangler@google.com49fdf182009-10-10 00:57:34 +0000378 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800379 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800380 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800381 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800382 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000383 g_main_loop_quit(loop_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800384
385 // Update counter
386 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000387 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800388
Darin Petkov9ce452b2010-11-17 14:33:28 -0800389 virtual void TransferTerminated(HttpFetcher* fetcher) {
390 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800391 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800392 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800393
rspangler@google.com49fdf182009-10-10 00:57:34 +0000394 GMainLoop* loop_;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800395
396 // Are we expecting an error response? (default: no)
397 bool is_expect_error_;
398
399 // Counters for callback invocations.
400 int times_transfer_complete_called_;
401 int times_transfer_terminated_called_;
402 int times_received_bytes_called_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000403};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000404
405struct StartTransferArgs {
406 HttpFetcher *http_fetcher;
407 string url;
408};
409
410gboolean StartTransfer(gpointer data) {
411 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
412 args->http_fetcher->BeginTransfer(args->url);
413 return FALSE;
414}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700415} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000416
417TYPED_TEST(HttpFetcherTest, SimpleTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700418 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000419 {
420 HttpFetcherTestDelegate delegate;
421 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800422 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000423 fetcher->set_delegate(&delegate);
424
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800425 scoped_ptr<HttpServer> server(this->test_.CreateServer());
426 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000427
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700428 StartTransferArgs start_xfer_args = {
429 fetcher.get(), this->test_.SmallUrl(server->GetPort())};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000430
431 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000432 g_main_loop_run(loop);
433 }
434 g_main_loop_unref(loop);
435}
436
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700437TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700438 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700439 {
440 HttpFetcherTestDelegate delegate;
441 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800442 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700443 fetcher->set_delegate(&delegate);
444
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800445 scoped_ptr<HttpServer> server(this->test_.CreateServer());
446 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700447
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700448 StartTransferArgs start_xfer_args = {
449 fetcher.get(), this->test_.BigUrl(server->GetPort())};
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700450
451 g_timeout_add(0, StartTransfer, &start_xfer_args);
452 g_main_loop_run(loop);
453 }
454 g_main_loop_unref(loop);
455}
456
Gilad Arnold48085ba2011-11-16 09:36:08 -0800457// Issue #9648: when server returns an error HTTP response, the fetcher needs to
458// terminate transfer prematurely, rather than try to process the error payload.
459TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800460 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800461 return;
462 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
463 {
464 HttpFetcherTestDelegate delegate;
465 delegate.loop_ = loop;
466
467 // Delegate should expect an error response.
468 delegate.is_expect_error_ = true;
469
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800470 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800471 fetcher->set_delegate(&delegate);
472
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800473 scoped_ptr<HttpServer> server(this->test_.CreateServer());
474 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800475
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800476 StartTransferArgs start_xfer_args = {
477 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700478 this->test_.ErrorUrl(server->GetPort())
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800479 };
Gilad Arnold48085ba2011-11-16 09:36:08 -0800480
481 g_timeout_add(0, StartTransfer, &start_xfer_args);
482 g_main_loop_run(loop);
483
484 // Make sure that no bytes were received.
485 CHECK_EQ(delegate.times_received_bytes_called_, 0);
Mike Frysinger0f9547d2012-02-16 12:11:37 -0500486 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800487
488 // Make sure that transfer completion was signaled once, and no termination
489 // was signaled.
490 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
491 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
492 }
493 g_main_loop_unref(loop);
494}
495
rspangler@google.com49fdf182009-10-10 00:57:34 +0000496namespace {
497class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
498 public:
499 virtual void ReceivedBytes(HttpFetcher* fetcher,
Alex Deymof9c59992014-04-02 21:16:59 -0700500 const char* /* bytes */, int /* length */) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000501 CHECK(!paused_);
502 paused_ = true;
503 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000504 }
505 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
506 g_main_loop_quit(loop_);
507 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800508 virtual void TransferTerminated(HttpFetcher* fetcher) {
509 ADD_FAILURE();
510 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000511 void Unpause() {
512 CHECK(paused_);
513 paused_ = false;
514 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000515 }
516 bool paused_;
517 HttpFetcher* fetcher_;
518 GMainLoop* loop_;
519};
520
521gboolean UnpausingTimeoutCallback(gpointer data) {
522 PausingHttpFetcherTestDelegate *delegate =
523 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
524 if (delegate->paused_)
525 delegate->Unpause();
526 return TRUE;
527}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700528} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000529
530TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700531 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000532 {
533 PausingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800534 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000535 delegate.paused_ = false;
536 delegate.loop_ = loop;
537 delegate.fetcher_ = fetcher.get();
538 fetcher->set_delegate(&delegate);
539
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800540 scoped_ptr<HttpServer> server(this->test_.CreateServer());
541 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800542
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800543 guint callback_id = g_timeout_add(kHttpResponseInternalServerError,
544 UnpausingTimeoutCallback, &delegate);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700545 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000546
547 g_main_loop_run(loop);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800548 g_source_remove(callback_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000549 }
550 g_main_loop_unref(loop);
551}
552
553namespace {
554class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
555 public:
556 virtual void ReceivedBytes(HttpFetcher* fetcher,
557 const char* bytes, int length) {}
558 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800559 ADD_FAILURE(); // We should never get here
rspangler@google.com49fdf182009-10-10 00:57:34 +0000560 g_main_loop_quit(loop_);
561 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800562 virtual void TransferTerminated(HttpFetcher* fetcher) {
563 EXPECT_EQ(fetcher, fetcher_.get());
564 EXPECT_FALSE(once_);
565 EXPECT_TRUE(callback_once_);
566 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700567 // The fetcher could have a callback scheduled on the ProxyResolver that
568 // can fire after this callback. We wait until the end of the test to
569 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800570 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000571 void TerminateTransfer() {
572 CHECK(once_);
573 once_ = false;
574 fetcher_->TerminateTransfer();
575 }
576 void EndLoop() {
577 g_main_loop_quit(loop_);
578 }
579 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800580 bool callback_once_;
581 scoped_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000582 GMainLoop* loop_;
583};
584
585gboolean AbortingTimeoutCallback(gpointer data) {
586 AbortingHttpFetcherTestDelegate *delegate =
587 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
588 if (delegate->once_) {
589 delegate->TerminateTransfer();
590 return TRUE;
591 } else {
592 delegate->EndLoop();
593 return FALSE;
594 }
595}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700596} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000597
598TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700599 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000600 {
601 AbortingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800602 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000603 delegate.once_ = true;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800604 delegate.callback_once_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000605 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800606 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000607
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800608 scoped_ptr<HttpServer> server(this->test_.CreateServer());
609 this->test_.IgnoreServerAborting(server.get());
610 ASSERT_TRUE(server->started_);
611
rspangler@google.com49fdf182009-10-10 00:57:34 +0000612 GSource* timeout_source_;
613 timeout_source_ = g_timeout_source_new(0); // ms
614 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
615 NULL);
616 g_source_attach(timeout_source_, NULL);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700617 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000618
619 g_main_loop_run(loop);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800620 CHECK(!delegate.once_);
621 CHECK(!delegate.callback_once_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000622 g_source_destroy(timeout_source_);
623 }
624 g_main_loop_unref(loop);
625}
626
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000627namespace {
628class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
629 public:
630 virtual void ReceivedBytes(HttpFetcher* fetcher,
631 const char* bytes, int length) {
632 data.append(bytes, length);
633 }
634 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700635 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800636 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000637 g_main_loop_quit(loop_);
638 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800639 virtual void TransferTerminated(HttpFetcher* fetcher) {
640 ADD_FAILURE();
641 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000642 string data;
643 GMainLoop* loop_;
644};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700645} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000646
647TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800648 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000649 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700650 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000651 {
652 FlakyHttpFetcherTestDelegate delegate;
653 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800654 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000655 fetcher->set_delegate(&delegate);
656
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800657 scoped_ptr<HttpServer> server(this->test_.CreateServer());
658 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000659
660 StartTransferArgs start_xfer_args = {
661 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700662 LocalServerUrlForPath(server->GetPort(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700663 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
664 kFlakyTruncateLength,
665 kFlakySleepEvery,
666 kFlakySleepSecs))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000667 };
668
669 g_timeout_add(0, StartTransfer, &start_xfer_args);
670 g_main_loop_run(loop);
671
672 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800673 ASSERT_EQ(kBigLength, delegate.data.size());
674 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000675 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
676 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
677 }
678 }
679 g_main_loop_unref(loop);
680}
681
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700682namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700683// This delegate kills the server attached to it after receiving any bytes.
684// This can be used for testing what happens when you try to fetch data and
685// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700686class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
687 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700688 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700689 : loop_(NULL),
690 server_(server) {}
691
692 virtual ~FailureHttpFetcherTestDelegate() {
693 if (server_) {
694 LOG(INFO) << "Stopping server in destructor";
695 delete server_;
696 LOG(INFO) << "server stopped";
697 }
698 }
699
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700700 virtual void ReceivedBytes(HttpFetcher* fetcher,
701 const char* bytes, int length) {
702 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700703 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700704 delete server_;
705 LOG(INFO) << "server stopped";
706 server_ = NULL;
707 }
708 }
709 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
710 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700711 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700712 g_main_loop_quit(loop_);
713 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800714 virtual void TransferTerminated(HttpFetcher* fetcher) {
715 ADD_FAILURE();
716 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700717 GMainLoop* loop_;
718 PythonHttpServer* server_;
719};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700720} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700721
722
723TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700724 // This test ensures that a fetcher responds correctly when a server isn't
725 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800726 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700727 return;
728 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
729 {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700730 FailureHttpFetcherTestDelegate delegate(NULL);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700731 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800732 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700733 fetcher->set_delegate(&delegate);
734
735 StartTransferArgs start_xfer_args = {
736 fetcher.get(),
Chris Sosa0a364bb2014-06-10 18:18:24 -0700737 "http://host_doesnt_exist99999999",
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700738 };
739
740 g_timeout_add(0, StartTransfer, &start_xfer_args);
741 g_main_loop_run(loop);
742
743 // Exiting and testing happens in the delegate
744 }
745 g_main_loop_unref(loop);
746}
747
748TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700749 // This test starts a new http server and kills it after receiving its first
750 // set of bytes. It test whether or not our fetcher eventually gives up on
751 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800752 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700753 return;
754 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
755 {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700756 PythonHttpServer* server = new PythonHttpServer();
757 int port = server->GetPort();
758 ASSERT_TRUE(server->started_);
759
760 // Handles destruction and claims ownership.
761 FailureHttpFetcherTestDelegate delegate(server);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700762 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800763 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700764 fetcher->set_delegate(&delegate);
765
766 StartTransferArgs start_xfer_args = {
767 fetcher.get(),
Chris Sosa0a364bb2014-06-10 18:18:24 -0700768 LocalServerUrlForPath(port,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700769 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
770 kFlakyTruncateLength,
771 kFlakySleepEvery,
772 kFlakySleepSecs))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700773 };
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700774 g_timeout_add(0, StartTransfer, &start_xfer_args);
775 g_main_loop_run(loop);
776
777 // Exiting and testing happens in the delegate
778 }
779 g_main_loop_unref(loop);
780}
781
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700782namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800783const HttpResponseCode kRedirectCodes[] = {
784 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
785 kHttpResponseTempRedirect
786};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700787
788class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
789 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700790 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700791 : expected_successful_(expected_successful) {}
792 virtual void ReceivedBytes(HttpFetcher* fetcher,
793 const char* bytes, int length) {
794 data.append(bytes, length);
795 }
796 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
797 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700798 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800799 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700800 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800801 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
802 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700803 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700804 g_main_loop_quit(loop_);
805 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800806 virtual void TransferTerminated(HttpFetcher* fetcher) {
807 ADD_FAILURE();
808 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700809 bool expected_successful_;
810 string data;
811 GMainLoop* loop_;
812};
813
814// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700815void RedirectTest(const HttpServer* server,
816 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700817 const string& url,
818 HttpFetcher* http_fetcher) {
819 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700820 {
821 RedirectHttpFetcherTestDelegate delegate(expected_successful);
822 delegate.loop_ = loop;
823 scoped_ptr<HttpFetcher> fetcher(http_fetcher);
824 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700825
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700826 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700827 { fetcher.get(), LocalServerUrlForPath(server->GetPort(), url) };
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700828
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700829 g_timeout_add(0, StartTransfer, &start_xfer_args);
830 g_main_loop_run(loop);
831 if (expected_successful) {
832 // verify the data we get back
833 ASSERT_EQ(kMediumLength, delegate.data.size());
834 for (int i = 0; i < kMediumLength; i += 10) {
835 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
836 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
837 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700838 }
839 }
840 g_main_loop_unref(loop);
841}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700842} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700843
844TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800845 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700846 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800847
848 scoped_ptr<HttpServer> server(this->test_.CreateServer());
849 ASSERT_TRUE(server->started_);
850
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700851 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800852 const string url = base::StringPrintf("/redirect/%d/download/%d",
853 kRedirectCodes[c],
854 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700855 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700856 }
857}
858
859TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800860 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700861 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800862
863 scoped_ptr<HttpServer> server(this->test_.CreateServer());
864 ASSERT_TRUE(server->started_);
865
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700866 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700867 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700868 url += base::StringPrintf("/redirect/%d",
869 kRedirectCodes[r % arraysize(kRedirectCodes)]);
870 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800871 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700872 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700873}
874
875TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800876 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700877 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800878
879 scoped_ptr<HttpServer> server(this->test_.CreateServer());
880 ASSERT_TRUE(server->started_);
881
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700882 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700883 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700884 url += base::StringPrintf("/redirect/%d",
885 kRedirectCodes[r % arraysize(kRedirectCodes)]);
886 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800887 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700888 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700889}
890
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700891namespace {
892class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
893 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700894 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700895 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800896
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700897 virtual void ReceivedBytes(HttpFetcher* fetcher,
898 const char* bytes, int length) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800899 EXPECT_EQ(fetcher, fetcher_.get());
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700900 data.append(bytes, length);
901 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800902
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700903 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800904 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800905 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700906 if (expected_response_code_ != 0)
907 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800908 // Destroy the fetcher (because we're allowed to).
909 fetcher_.reset(NULL);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700910 g_main_loop_quit(loop_);
911 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800912
Darin Petkov9ce452b2010-11-17 14:33:28 -0800913 virtual void TransferTerminated(HttpFetcher* fetcher) {
914 ADD_FAILURE();
915 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800916
Darin Petkov9ce452b2010-11-17 14:33:28 -0800917 scoped_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700918 int expected_response_code_;
919 string data;
920 GMainLoop* loop_;
921};
922
923void MultiTest(HttpFetcher* fetcher_in,
924 const string& url,
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800925 const vector<pair<off_t, off_t> >& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700926 const string& expected_prefix,
927 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800928 HttpResponseCode expected_response_code) {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700929 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
930 {
931 MultiHttpFetcherTestDelegate delegate(expected_response_code);
932 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800933 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -0700934
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800935 MultiRangeHttpFetcher* multi_fetcher =
936 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700937 ASSERT_TRUE(multi_fetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800938 multi_fetcher->ClearRanges();
939 for (vector<pair<off_t, off_t> >::const_iterator it = ranges.begin(),
940 e = ranges.end(); it != e; ++it) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700941 std::string tmp_str = base::StringPrintf("%jd+", it->first);
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800942 if (it->second > 0) {
943 base::StringAppendF(&tmp_str, "%jd", it->second);
944 multi_fetcher->AddRange(it->first, it->second);
945 } else {
946 base::StringAppendF(&tmp_str, "?");
947 multi_fetcher->AddRange(it->first);
948 }
949 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800950 }
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700951 dynamic_cast<FakeSystemState*>(fetcher_in->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -0700952 ->fake_hardware()->SetIsOfficialBuild(false);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800953 multi_fetcher->set_delegate(&delegate);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700954
Darin Petkov9ce452b2010-11-17 14:33:28 -0800955 StartTransferArgs start_xfer_args = {multi_fetcher, url};
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700956
957 g_timeout_add(0, StartTransfer, &start_xfer_args);
958 g_main_loop_run(loop);
959
960 EXPECT_EQ(expected_size, delegate.data.size());
961 EXPECT_EQ(expected_prefix,
962 string(delegate.data.data(), expected_prefix.size()));
963 }
964 g_main_loop_unref(loop);
965}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700966} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700967
Darin Petkov9ce452b2010-11-17 14:33:28 -0800968TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800969 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700970 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800971
972 scoped_ptr<HttpServer> server(this->test_.CreateServer());
973 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700974
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800975 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700976 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800977 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800978 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700979 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700980 ranges,
981 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800982 kBigLength - (99 - 25),
983 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700984}
985
986TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800987 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700988 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800989
990 scoped_ptr<HttpServer> server(this->test_.CreateServer());
991 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700992
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800993 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700994 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800995 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700996 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700997 ranges,
998 "abcdefghijabcdefghijabcd",
999 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001000 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001001}
1002
1003TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001004 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001005 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001006
1007 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1008 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001009
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001010 vector<pair<off_t, off_t> > ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001011 ranges.push_back(make_pair(kBigLength - 2, 0));
1012 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001013 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001014 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001015 ranges,
1016 "ijhij",
1017 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001018 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001019}
1020
1021TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001022 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001023 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001024
1025 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1026 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001027
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001028 vector<pair<off_t, off_t> > ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001029 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001030 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001031 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001032 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001033 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001034 ranges,
1035 "ij",
1036 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001037 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001038 ranges.push_back(make_pair(0, 5));
1039 }
1040}
1041
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001042// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1043// should retry with other proxies listed before giving up.
1044//
1045// (1) successful recovery: The offset fetch will fail twice but succeed with
1046// the third proxy.
1047TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1048 if (!this->test_.IsMulti())
1049 return;
1050
1051 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1052 ASSERT_TRUE(server->started_);
1053
1054 vector<pair<off_t, off_t> > ranges;
1055 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001056 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001057 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001058 LocalServerUrlForPath(server->GetPort(),
1059 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001060 kBigLength)),
1061 ranges,
1062 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1063 kBigLength - (99 - 25),
1064 kHttpResponsePartialContent);
1065}
1066
1067// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1068// fetcher will signal a (failed) completed transfer to the delegate.
1069TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1070 if (!this->test_.IsMulti())
1071 return;
1072
1073 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1074 ASSERT_TRUE(server->started_);
1075
1076 vector<pair<off_t, off_t> > ranges;
1077 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001078 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001079 MultiTest(this->test_.NewLargeFetcher(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001080 LocalServerUrlForPath(server->GetPort(),
1081 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001082 kBigLength)),
1083 ranges,
1084 "abcdefghijabcdefghijabcde", // only received the first chunk
1085 25,
1086 kHttpResponseUndefined);
1087}
1088
1089
1090
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001091namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001092class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001093 public:
1094 virtual void ReceivedBytes(HttpFetcher* fetcher,
1095 const char* bytes, int length) {
1096 ADD_FAILURE();
1097 }
1098 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
1099 EXPECT_FALSE(successful);
1100 g_main_loop_quit(loop_);
1101 }
Darin Petkov9ce452b2010-11-17 14:33:28 -08001102 virtual void TransferTerminated(HttpFetcher* fetcher) {
1103 ADD_FAILURE();
1104 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001105 GMainLoop* loop_;
1106};
1107
1108} // namespace
1109
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001110TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001111 if (this->test_.IsMock() || this->test_.IsMulti())
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001112 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001113
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001114 for (int i = 0; i < 2; i++) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001115 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1116 ASSERT_TRUE(server->started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001117
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001118 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001119 {
1120 BlockedTransferTestDelegate delegate;
1121 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001122
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001123 bool is_allowed = (i != 0);
1124 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Jay Srinivasan43488792012-06-19 00:25:31 -07001125
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001126 bool is_official_build = (i == 1);
1127 LOG(INFO) << "is_update_allowed_over_connection: " << is_allowed;
1128 LOG(INFO) << "is_official_build: " << is_official_build;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001129 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
1130 dynamic_cast<FakeSystemState*>(fetcher->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -07001131 ->fake_hardware()->SetIsOfficialBuild(is_official_build);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001132 fetcher->set_delegate(&delegate);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001133
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001134 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001135 {fetcher.get(),
1136 LocalServerUrlForPath(server->GetPort(),
1137 this->test_.SmallUrl(server->GetPort()))};
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001138
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001139 g_timeout_add(0, StartTransfer, &start_xfer_args);
1140 g_main_loop_run(loop);
1141 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001142 g_main_loop_unref(loop);
1143 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001144}
1145
rspangler@google.com49fdf182009-10-10 00:57:34 +00001146} // namespace chromeos_update_engine