blob: f49c56386817006f8595c77c12df1d24d4035450 [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>
Andrew de los Reyes45168102010-11-22 11:13:50 -080016#include <base/string_util.h>
Mike Frysinger8155d082012-04-06 15:23:18 -040017#include <base/stringprintf.h>
Gilad Arnold8e3f1262013-01-08 14:59:54 -080018#include <base/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 Arnold9bedeb52011-11-17 16:19:57 -080023#include "update_engine/http_common.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000024#include "update_engine/libcurl_http_fetcher.h"
Jay Srinivasan43488792012-06-19 00:25:31 -070025#include "update_engine/mock_connection_manager.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000026#include "update_engine/mock_http_fetcher.h"
Jay Srinivasan08fce042012-06-07 16:31:01 -070027#include "update_engine/mock_system_state.h"
Andrew de los Reyes819fef22010-12-17 11:33:58 -080028#include "update_engine/multi_range_http_fetcher.h"
Andrew de los Reyes45168102010-11-22 11:13:50 -080029#include "update_engine/proxy_resolver.h"
Jay Srinivasan08fce042012-06-07 16:31:01 -070030#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000031
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070032using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080033using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000034using std::string;
35using std::vector;
36
Gilad Arnold8e3f1262013-01-08 14:59:54 -080037using base::TimeDelta;
Jay Srinivasan43488792012-06-19 00:25:31 -070038using testing::_;
39using testing::SetArgumentPointee;
40using testing::DoAll;
41using testing::Return;
42
Gilad Arnold9bedeb52011-11-17 16:19:57 -080043namespace {
44
45const int kBigLength = 100000;
46const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080047const int kFlakyTruncateLength = 29000;
48const int kFlakySleepEvery = 3;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080049const int kFlakySleepSecs = 10;
50
51} // namespace
52
rspangler@google.com49fdf182009-10-10 00:57:34 +000053namespace chromeos_update_engine {
54
Gilad Arnold9bedeb52011-11-17 16:19:57 -080055static const char *kUnusedUrl = "unused://unused";
56
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070057static inline string LocalServerUrlForPath(in_port_t port,
58 const string& path) {
59 string port_str = (port ? StringPrintf(":%hu", port) : "");
60 return base::StringPrintf("http://127.0.0.1%s%s", port_str.c_str(),
61 path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000062}
63
Gilad Arnold9bedeb52011-11-17 16:19:57 -080064//
65// Class hierarchy for HTTP server implementations.
66//
67
68class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000069 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080070 // This makes it an abstract class (dirty but works).
71 virtual ~HttpServer() = 0;
72
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070073 virtual in_port_t GetPort() const {
74 return 0;
75 }
76
rspangler@google.com49fdf182009-10-10 00:57:34 +000077 bool started_;
78};
79
Gilad Arnold9bedeb52011-11-17 16:19:57 -080080HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +000081
Gilad Arnold9bedeb52011-11-17 16:19:57 -080082
83class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000084 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080085 NullHttpServer() {
86 started_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +000087 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000088};
89
Gilad Arnold9bedeb52011-11-17 16:19:57 -080090
91class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000092 public:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070093 PythonHttpServer() : pid_(-1), port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000094 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070095
96 // Spawn the server process.
97 gchar *argv[] = {
98 const_cast<gchar*>("./test_http_server"),
99 NULL };
100 GError *err;
101 gint server_stdout = -1;
102 if (!g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
103 NULL, NULL, &pid_, NULL, &server_stdout, NULL,
104 &err)) {
105 LOG(ERROR) << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000106 return;
107 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700108 CHECK_GT(pid_, 0);
109 CHECK_GE(server_stdout, 0);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700110 LOG(INFO) << "started http server with pid " << pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700111
112 // Wait for server to begin accepting connections, obtain its port.
113 char line[80];
114 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
115 CHECK_GT(sizeof(line), listening_msg_prefix_len);
116 int line_len = read(server_stdout, line, sizeof(line) - 1);
117 if (line_len <= static_cast<int>(listening_msg_prefix_len)) {
118 if (line_len < 0) {
119 LOG(ERROR) << "error reading http server stdout: "
120 << strerror(errno);
121 } else {
122 LOG(ERROR) << "server output too short";
123 }
124 Terminate(true);
125 return;
126 }
127
128 line[line_len] = '\0';
129 CHECK_EQ(strstr(line, kServerListeningMsgPrefix), line);
130 const char* listening_port_str = line + listening_msg_prefix_len;
131 char* end_ptr;
132 long raw_port = strtol(listening_port_str, &end_ptr, 10);
133 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:
Jay Srinivasan43488792012-06-19 00:25:31 -0700197 AnyHttpFetcherTest()
198 : mock_connection_manager_(&mock_system_state_) {
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800199 mock_system_state_.set_connection_manager(&mock_connection_manager_);
Jay Srinivasan43488792012-06-19 00:25:31 -0700200 }
201
202 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800203 HttpFetcher* NewLargeFetcher() {
204 return NewLargeFetcher(1);
205 }
206
207 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) = 0;
208 HttpFetcher* NewSmallFetcher() {
209 return NewSmallFetcher(1);
210 }
211
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700212 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
213 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
214 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800215
216 virtual bool IsMock() const = 0;
217 virtual bool IsMulti() const = 0;
218
219 virtual void IgnoreServerAborting(HttpServer* server) const {}
220
221 virtual HttpServer *CreateServer() = 0;
222
223 protected:
224 DirectProxyResolver proxy_resolver_;
Jay Srinivasan43488792012-06-19 00:25:31 -0700225 MockSystemState mock_system_state_;
226 MockConnectionManager mock_connection_manager_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800227};
228
229class MockHttpFetcherTest : public AnyHttpFetcherTest {
230 public:
231 // Necessary to unhide the definition in the base class.
232 using AnyHttpFetcherTest::NewLargeFetcher;
233 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) {
234 vector<char> big_data(1000000);
235 CHECK(num_proxies > 0);
236 proxy_resolver_.set_num_proxies(num_proxies);
237 return new MockHttpFetcher(
238 big_data.data(),
239 big_data.size(),
240 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
241 }
242
243 // Necessary to unhide the definition in the base class.
244 using AnyHttpFetcherTest::NewSmallFetcher;
245 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) {
246 CHECK(num_proxies > 0);
247 proxy_resolver_.set_num_proxies(num_proxies);
248 return new MockHttpFetcher(
249 "x",
250 1,
251 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
252 }
253
254 virtual bool IsMock() const { return true; }
255 virtual bool IsMulti() const { return false; }
256
257 virtual HttpServer *CreateServer() {
258 return new NullHttpServer;
259 }
260};
261
262class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
263 public:
264 // Necessary to unhide the definition in the base class.
265 using AnyHttpFetcherTest::NewLargeFetcher;
266 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) {
267 CHECK(num_proxies > 0);
268 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes45168102010-11-22 11:13:50 -0800269 LibcurlHttpFetcher *ret = new
Jay Srinivasan08fce042012-06-07 16:31:01 -0700270 LibcurlHttpFetcher(reinterpret_cast<ProxyResolver*>(&proxy_resolver_),
Gilad Arnold7c04e762012-05-23 10:54:02 -0700271 &mock_system_state_, false);
Darin Petkovb83371f2010-08-17 09:34:49 -0700272 // Speed up test execution.
273 ret->set_idle_seconds(1);
274 ret->set_retry_seconds(1);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700275 ret->SetBuildType(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000276 return ret;
277 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800278
279 // Necessary to unhide the definition in the base class.
280 using AnyHttpFetcherTest::NewSmallFetcher;
281 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) {
282 return NewLargeFetcher(num_proxies);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000283 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800284
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700285 virtual string BigUrl(in_port_t port) const {
286 return LocalServerUrlForPath(port,
287 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800288 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000289 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700290 virtual string SmallUrl(in_port_t port) const {
291 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000292 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700293 virtual string ErrorUrl(in_port_t port) const {
294 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800295 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800296
297 virtual bool IsMock() const { return false; }
298 virtual bool IsMulti() const { return false; }
299
300 virtual void IgnoreServerAborting(HttpServer* server) const {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700301 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700302 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800303
304 virtual HttpServer *CreateServer() {
305 return new PythonHttpServer;
306 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000307};
308
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800309class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700310 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800311 // Necessary to unhide the definition in the base class.
312 using AnyHttpFetcherTest::NewLargeFetcher;
313 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) {
314 CHECK(num_proxies > 0);
315 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800316 ProxyResolver* resolver =
317 reinterpret_cast<ProxyResolver*>(&proxy_resolver_);
Gilad Arnold7c04e762012-05-23 10:54:02 -0700318 MultiRangeHttpFetcher *ret =
319 new MultiRangeHttpFetcher(
320 new LibcurlHttpFetcher(resolver, &mock_system_state_, false));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800321 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800322 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700323 // Speed up test execution.
324 ret->set_idle_seconds(1);
325 ret->set_retry_seconds(1);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700326 ret->SetBuildType(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700327 return ret;
328 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800329
330 // Necessary to unhide the definition in the base class.
331 using AnyHttpFetcherTest::NewSmallFetcher;
332 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) {
333 return NewLargeFetcher(num_proxies);
334 }
335
336 virtual bool IsMulti() const { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700337};
338
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800339
340//
341// Infrastructure for type tests of HTTP fetcher.
342// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
343//
344
345// Fixture class template. We use an explicit constraint to guarantee that it
346// can only be instantiated with an AnyHttpFetcherTest type, see:
347// http://www2.research.att.com/~bs/bs_faq2.html#constraints
348template <typename T>
349class HttpFetcherTest : public ::testing::Test {
350 public:
351 T test_;
352
353 private:
354 static void TypeConstraint(T *a) {
355 AnyHttpFetcherTest *b = a;
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700356 if (b == 0) // Silence compiler warning of unused variable.
357 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800358 }
359};
360
361// Test case types list.
362typedef ::testing::Types<LibcurlHttpFetcherTest,
363 MockHttpFetcherTest,
364 MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000365TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
366
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800367
rspangler@google.com49fdf182009-10-10 00:57:34 +0000368namespace {
369class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000370 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800371 HttpFetcherTestDelegate() :
Gilad Arnold48085ba2011-11-16 09:36:08 -0800372 is_expect_error_(false), times_transfer_complete_called_(0),
373 times_transfer_terminated_called_(0), times_received_bytes_called_(0) {}
374
rspangler@google.com49fdf182009-10-10 00:57:34 +0000375 virtual void ReceivedBytes(HttpFetcher* fetcher,
376 const char* bytes, int length) {
377 char str[length + 1];
378 memset(str, 0, length + 1);
379 memcpy(str, bytes, length);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800380
381 // Update counters
382 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000383 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800384
rspangler@google.com49fdf182009-10-10 00:57:34 +0000385 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800386 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800387 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800388 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800389 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000390 g_main_loop_quit(loop_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800391
392 // Update counter
393 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000394 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800395
Darin Petkov9ce452b2010-11-17 14:33:28 -0800396 virtual void TransferTerminated(HttpFetcher* fetcher) {
397 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800398 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800399 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800400
rspangler@google.com49fdf182009-10-10 00:57:34 +0000401 GMainLoop* loop_;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800402
403 // Are we expecting an error response? (default: no)
404 bool is_expect_error_;
405
406 // Counters for callback invocations.
407 int times_transfer_complete_called_;
408 int times_transfer_terminated_called_;
409 int times_received_bytes_called_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000410};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000411
412struct StartTransferArgs {
413 HttpFetcher *http_fetcher;
414 string url;
415};
416
417gboolean StartTransfer(gpointer data) {
418 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
419 args->http_fetcher->BeginTransfer(args->url);
420 return FALSE;
421}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000422} // namespace {}
423
424TYPED_TEST(HttpFetcherTest, SimpleTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700425 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000426 {
427 HttpFetcherTestDelegate delegate;
428 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800429 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000430 fetcher->set_delegate(&delegate);
431
Jay Srinivasan43488792012-06-19 00:25:31 -0700432 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800433 fetcher->GetSystemState()->connection_manager());
Jay Srinivasan43488792012-06-19 00:25:31 -0700434 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
435 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi), Return(true)));
436 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi))
437 .WillRepeatedly(Return(true));
438 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
439 .WillRepeatedly(Return(flimflam::kTypeWifi));
440
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800441 scoped_ptr<HttpServer> server(this->test_.CreateServer());
442 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000443
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700444 StartTransferArgs start_xfer_args = {
445 fetcher.get(), this->test_.SmallUrl(server->GetPort())};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000446
447 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000448 g_main_loop_run(loop);
449 }
450 g_main_loop_unref(loop);
451}
452
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700453TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700454 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700455 {
456 HttpFetcherTestDelegate delegate;
457 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800458 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700459 fetcher->set_delegate(&delegate);
460
Jay Srinivasan43488792012-06-19 00:25:31 -0700461 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800462 fetcher->GetSystemState()->connection_manager());
Jay Srinivasan43488792012-06-19 00:25:31 -0700463 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
464 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet), Return(true)));
465 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet))
466 .WillRepeatedly(Return(true));
467 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
468 .WillRepeatedly(Return(flimflam::kTypeEthernet));
469
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800470 scoped_ptr<HttpServer> server(this->test_.CreateServer());
471 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700472
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700473 StartTransferArgs start_xfer_args = {
474 fetcher.get(), this->test_.BigUrl(server->GetPort())};
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700475
476 g_timeout_add(0, StartTransfer, &start_xfer_args);
477 g_main_loop_run(loop);
478 }
479 g_main_loop_unref(loop);
480}
481
Gilad Arnold48085ba2011-11-16 09:36:08 -0800482// Issue #9648: when server returns an error HTTP response, the fetcher needs to
483// terminate transfer prematurely, rather than try to process the error payload.
484TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800485 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800486 return;
487 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
488 {
489 HttpFetcherTestDelegate delegate;
490 delegate.loop_ = loop;
491
492 // Delegate should expect an error response.
493 delegate.is_expect_error_ = true;
494
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800495 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800496 fetcher->set_delegate(&delegate);
497
Jay Srinivasan43488792012-06-19 00:25:31 -0700498 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800499 fetcher->GetSystemState()->connection_manager());
Jay Srinivasan43488792012-06-19 00:25:31 -0700500 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
501 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWimax), Return(true)));
502 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWimax))
503 .WillRepeatedly(Return(true));
504 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWimax))
505 .WillRepeatedly(Return(flimflam::kTypeWimax));
506
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800507 scoped_ptr<HttpServer> server(this->test_.CreateServer());
508 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800509
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800510 StartTransferArgs start_xfer_args = {
511 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700512 this->test_.ErrorUrl(server->GetPort())
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800513 };
Gilad Arnold48085ba2011-11-16 09:36:08 -0800514
515 g_timeout_add(0, StartTransfer, &start_xfer_args);
516 g_main_loop_run(loop);
517
518 // Make sure that no bytes were received.
519 CHECK_EQ(delegate.times_received_bytes_called_, 0);
Mike Frysinger0f9547d2012-02-16 12:11:37 -0500520 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800521
522 // Make sure that transfer completion was signaled once, and no termination
523 // was signaled.
524 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
525 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
526 }
527 g_main_loop_unref(loop);
528}
529
rspangler@google.com49fdf182009-10-10 00:57:34 +0000530namespace {
531class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
532 public:
533 virtual void ReceivedBytes(HttpFetcher* fetcher,
534 const char* bytes, int length) {
535 char str[length + 1];
rspangler@google.com49fdf182009-10-10 00:57:34 +0000536 memset(str, 0, length + 1);
537 memcpy(str, bytes, length);
538 CHECK(!paused_);
539 paused_ = true;
540 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000541 }
542 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
543 g_main_loop_quit(loop_);
544 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800545 virtual void TransferTerminated(HttpFetcher* fetcher) {
546 ADD_FAILURE();
547 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000548 void Unpause() {
549 CHECK(paused_);
550 paused_ = false;
551 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000552 }
553 bool paused_;
554 HttpFetcher* fetcher_;
555 GMainLoop* loop_;
556};
557
558gboolean UnpausingTimeoutCallback(gpointer data) {
559 PausingHttpFetcherTestDelegate *delegate =
560 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
561 if (delegate->paused_)
562 delegate->Unpause();
563 return TRUE;
564}
565} // namespace {}
566
567TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700568 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000569 {
570 PausingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800571 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000572 delegate.paused_ = false;
573 delegate.loop_ = loop;
574 delegate.fetcher_ = fetcher.get();
575 fetcher->set_delegate(&delegate);
576
Jay Srinivasan43488792012-06-19 00:25:31 -0700577 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800578 fetcher->GetSystemState()->connection_manager());
Jay Srinivasan43488792012-06-19 00:25:31 -0700579 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
580 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetCellular), Return(true)));
581 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetCellular))
582 .WillRepeatedly(Return(true));
583 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetCellular))
584 .WillRepeatedly(Return(flimflam::kTypeCellular));
585
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800586 scoped_ptr<HttpServer> server(this->test_.CreateServer());
587 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800588
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800589 guint callback_id = g_timeout_add(kHttpResponseInternalServerError,
590 UnpausingTimeoutCallback, &delegate);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700591 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000592
593 g_main_loop_run(loop);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800594 g_source_remove(callback_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000595 }
596 g_main_loop_unref(loop);
597}
598
599namespace {
600class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
601 public:
602 virtual void ReceivedBytes(HttpFetcher* fetcher,
603 const char* bytes, int length) {}
604 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800605 ADD_FAILURE(); // We should never get here
rspangler@google.com49fdf182009-10-10 00:57:34 +0000606 g_main_loop_quit(loop_);
607 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800608 virtual void TransferTerminated(HttpFetcher* fetcher) {
609 EXPECT_EQ(fetcher, fetcher_.get());
610 EXPECT_FALSE(once_);
611 EXPECT_TRUE(callback_once_);
612 callback_once_ = false;
613 // |fetcher| can be destroyed during this callback.
614 fetcher_.reset(NULL);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800615 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000616 void TerminateTransfer() {
617 CHECK(once_);
618 once_ = false;
619 fetcher_->TerminateTransfer();
620 }
621 void EndLoop() {
622 g_main_loop_quit(loop_);
623 }
624 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800625 bool callback_once_;
626 scoped_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000627 GMainLoop* loop_;
628};
629
630gboolean AbortingTimeoutCallback(gpointer data) {
631 AbortingHttpFetcherTestDelegate *delegate =
632 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
633 if (delegate->once_) {
634 delegate->TerminateTransfer();
635 return TRUE;
636 } else {
637 delegate->EndLoop();
638 return FALSE;
639 }
640}
641} // namespace {}
642
643TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700644 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000645 {
646 AbortingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800647 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000648 delegate.once_ = true;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800649 delegate.callback_once_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000650 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800651 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000652
Jay Srinivasan43488792012-06-19 00:25:31 -0700653 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800654 delegate.fetcher_->GetSystemState()->connection_manager());
Jay Srinivasan43488792012-06-19 00:25:31 -0700655 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
656 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi), Return(true)));
657 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi))
658 .WillRepeatedly(Return(true));
659 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
660 .WillRepeatedly(Return(flimflam::kTypeWifi));
661
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800662 scoped_ptr<HttpServer> server(this->test_.CreateServer());
663 this->test_.IgnoreServerAborting(server.get());
664 ASSERT_TRUE(server->started_);
665
rspangler@google.com49fdf182009-10-10 00:57:34 +0000666 GSource* timeout_source_;
667 timeout_source_ = g_timeout_source_new(0); // ms
668 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
669 NULL);
670 g_source_attach(timeout_source_, NULL);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700671 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000672
673 g_main_loop_run(loop);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800674 CHECK(!delegate.once_);
675 CHECK(!delegate.callback_once_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000676 g_source_destroy(timeout_source_);
677 }
678 g_main_loop_unref(loop);
679}
680
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000681namespace {
682class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
683 public:
684 virtual void ReceivedBytes(HttpFetcher* fetcher,
685 const char* bytes, int length) {
686 data.append(bytes, length);
687 }
688 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700689 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800690 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000691 g_main_loop_quit(loop_);
692 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800693 virtual void TransferTerminated(HttpFetcher* fetcher) {
694 ADD_FAILURE();
695 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000696 string data;
697 GMainLoop* loop_;
698};
699} // namespace {}
700
701TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800702 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000703 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700704 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000705 {
706 FlakyHttpFetcherTestDelegate delegate;
707 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800708 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000709 fetcher->set_delegate(&delegate);
710
Jay Srinivasan43488792012-06-19 00:25:31 -0700711 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800712 fetcher->GetSystemState()->connection_manager());
Jay Srinivasan43488792012-06-19 00:25:31 -0700713 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
714 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi), Return(true)));
715 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi))
716 .WillRepeatedly(Return(true));
717 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
718 .WillRepeatedly(Return(flimflam::kTypeWifi));
719
720
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800721 scoped_ptr<HttpServer> server(this->test_.CreateServer());
722 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000723
724 StartTransferArgs start_xfer_args = {
725 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700726 LocalServerUrlForPath(server->GetPort(),
727 StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800728 kFlakyTruncateLength,
729 kFlakySleepEvery,
730 kFlakySleepSecs))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000731 };
732
733 g_timeout_add(0, StartTransfer, &start_xfer_args);
734 g_main_loop_run(loop);
735
736 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800737 ASSERT_EQ(kBigLength, delegate.data.size());
738 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000739 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
740 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
741 }
742 }
743 g_main_loop_unref(loop);
744}
745
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700746namespace {
747class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
748 public:
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700749 FailureHttpFetcherTestDelegate(PythonHttpServer* server)
750 : loop_(NULL),
751 server_(server) {}
752
753 virtual ~FailureHttpFetcherTestDelegate() {
754 if (server_) {
755 LOG(INFO) << "Stopping server in destructor";
756 delete server_;
757 LOG(INFO) << "server stopped";
758 }
759 }
760
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700761 virtual void ReceivedBytes(HttpFetcher* fetcher,
762 const char* bytes, int length) {
763 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700764 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700765 delete server_;
766 LOG(INFO) << "server stopped";
767 server_ = NULL;
768 }
769 }
770 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
771 EXPECT_FALSE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700772 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700773 g_main_loop_quit(loop_);
774 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800775 virtual void TransferTerminated(HttpFetcher* fetcher) {
776 ADD_FAILURE();
777 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700778 GMainLoop* loop_;
779 PythonHttpServer* server_;
780};
781} // namespace {}
782
783
784TYPED_TEST(HttpFetcherTest, FailureTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800785 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700786 return;
787 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
788 {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700789 FailureHttpFetcherTestDelegate delegate(NULL);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700790 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800791 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700792 fetcher->set_delegate(&delegate);
793
Jay Srinivasan43488792012-06-19 00:25:31 -0700794 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800795 fetcher->GetSystemState()->connection_manager());
Jay Srinivasan43488792012-06-19 00:25:31 -0700796 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
797 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet), Return(true)));
798 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet))
799 .WillRepeatedly(Return(true));
800 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
801 .WillRepeatedly(Return(flimflam::kTypeEthernet));
802
803
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700804 StartTransferArgs start_xfer_args = {
805 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700806 LocalServerUrlForPath(0, this->test_.SmallUrl(0))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700807 };
808
809 g_timeout_add(0, StartTransfer, &start_xfer_args);
810 g_main_loop_run(loop);
811
812 // Exiting and testing happens in the delegate
813 }
814 g_main_loop_unref(loop);
815}
816
817TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800818 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700819 return;
820 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
821 {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700822 FailureHttpFetcherTestDelegate delegate(new PythonHttpServer);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700823 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800824 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700825 fetcher->set_delegate(&delegate);
826
827 StartTransferArgs start_xfer_args = {
828 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700829 LocalServerUrlForPath(0,
830 StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800831 kFlakyTruncateLength,
832 kFlakySleepEvery,
833 kFlakySleepSecs))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700834 };
835
836 g_timeout_add(0, StartTransfer, &start_xfer_args);
837 g_main_loop_run(loop);
838
839 // Exiting and testing happens in the delegate
840 }
841 g_main_loop_unref(loop);
842}
843
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700844namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800845const HttpResponseCode kRedirectCodes[] = {
846 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
847 kHttpResponseTempRedirect
848};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700849
850class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
851 public:
852 RedirectHttpFetcherTestDelegate(bool expected_successful)
853 : expected_successful_(expected_successful) {}
854 virtual void ReceivedBytes(HttpFetcher* fetcher,
855 const char* bytes, int length) {
856 data.append(bytes, length);
857 }
858 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
859 EXPECT_EQ(expected_successful_, successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700860 if (expected_successful_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800861 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Darin Petkovcb466212010-08-26 09:40:11 -0700862 else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800863 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
864 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700865 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700866 g_main_loop_quit(loop_);
867 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800868 virtual void TransferTerminated(HttpFetcher* fetcher) {
869 ADD_FAILURE();
870 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700871 bool expected_successful_;
872 string data;
873 GMainLoop* loop_;
874};
875
876// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700877void RedirectTest(const HttpServer* server,
878 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700879 const string& url,
880 HttpFetcher* http_fetcher) {
881 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700882 {
883 RedirectHttpFetcherTestDelegate delegate(expected_successful);
884 delegate.loop_ = loop;
885 scoped_ptr<HttpFetcher> fetcher(http_fetcher);
886 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700887
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700888 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800889 fetcher->GetSystemState()->connection_manager());
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700890 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
891 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet), Return(true)));
892 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet))
893 .WillRepeatedly(Return(true));
894 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
895 .WillRepeatedly(Return(flimflam::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700896
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700897 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700898 { fetcher.get(), LocalServerUrlForPath(server->GetPort(), url) };
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700899
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700900 g_timeout_add(0, StartTransfer, &start_xfer_args);
901 g_main_loop_run(loop);
902 if (expected_successful) {
903 // verify the data we get back
904 ASSERT_EQ(kMediumLength, delegate.data.size());
905 for (int i = 0; i < kMediumLength; i += 10) {
906 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
907 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
908 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700909 }
910 }
911 g_main_loop_unref(loop);
912}
913} // namespace {}
914
915TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800916 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700917 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800918
919 scoped_ptr<HttpServer> server(this->test_.CreateServer());
920 ASSERT_TRUE(server->started_);
921
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700922 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800923 const string url = base::StringPrintf("/redirect/%d/download/%d",
924 kRedirectCodes[c],
925 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700926 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700927 }
928}
929
930TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800931 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700932 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800933
934 scoped_ptr<HttpServer> server(this->test_.CreateServer());
935 ASSERT_TRUE(server->started_);
936
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700937 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700938 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700939 url += base::StringPrintf("/redirect/%d",
940 kRedirectCodes[r % arraysize(kRedirectCodes)]);
941 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800942 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700943 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700944}
945
946TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800947 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700948 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800949
950 scoped_ptr<HttpServer> server(this->test_.CreateServer());
951 ASSERT_TRUE(server->started_);
952
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700953 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700954 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700955 url += base::StringPrintf("/redirect/%d",
956 kRedirectCodes[r % arraysize(kRedirectCodes)]);
957 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800958 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700959 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700960}
961
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700962namespace {
963class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
964 public:
965 MultiHttpFetcherTestDelegate(int expected_response_code)
966 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800967
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700968 virtual void ReceivedBytes(HttpFetcher* fetcher,
969 const char* bytes, int length) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800970 EXPECT_EQ(fetcher, fetcher_.get());
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700971 data.append(bytes, length);
972 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800973
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700974 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800975 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800976 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700977 if (expected_response_code_ != 0)
978 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800979 // Destroy the fetcher (because we're allowed to).
980 fetcher_.reset(NULL);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700981 g_main_loop_quit(loop_);
982 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800983
Darin Petkov9ce452b2010-11-17 14:33:28 -0800984 virtual void TransferTerminated(HttpFetcher* fetcher) {
985 ADD_FAILURE();
986 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800987
Darin Petkov9ce452b2010-11-17 14:33:28 -0800988 scoped_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700989 int expected_response_code_;
990 string data;
991 GMainLoop* loop_;
992};
993
994void MultiTest(HttpFetcher* fetcher_in,
995 const string& url,
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800996 const vector<pair<off_t, off_t> >& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700997 const string& expected_prefix,
998 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800999 HttpResponseCode expected_response_code) {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001000 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
1001 {
1002 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1003 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -08001004 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001005
1006 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08001007 fetcher_in->GetSystemState()->connection_manager());
Jay Srinivasan43488792012-06-19 00:25:31 -07001008 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
1009 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi), Return(true)));
1010 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi))
1011 .WillRepeatedly(Return(true));
1012 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
1013 .WillRepeatedly(Return(flimflam::kTypeWifi));
1014
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001015 MultiRangeHttpFetcher* multi_fetcher =
1016 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001017 ASSERT_TRUE(multi_fetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001018 multi_fetcher->ClearRanges();
1019 for (vector<pair<off_t, off_t> >::const_iterator it = ranges.begin(),
1020 e = ranges.end(); it != e; ++it) {
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001021 std::string tmp_str = StringPrintf("%jd+", it->first);
1022 if (it->second > 0) {
1023 base::StringAppendF(&tmp_str, "%jd", it->second);
1024 multi_fetcher->AddRange(it->first, it->second);
1025 } else {
1026 base::StringAppendF(&tmp_str, "?");
1027 multi_fetcher->AddRange(it->first);
1028 }
1029 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001030 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001031 multi_fetcher->SetBuildType(false);
Darin Petkov9ce452b2010-11-17 14:33:28 -08001032 multi_fetcher->set_delegate(&delegate);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001033
Darin Petkov9ce452b2010-11-17 14:33:28 -08001034 StartTransferArgs start_xfer_args = {multi_fetcher, url};
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001035
1036 g_timeout_add(0, StartTransfer, &start_xfer_args);
1037 g_main_loop_run(loop);
1038
1039 EXPECT_EQ(expected_size, delegate.data.size());
1040 EXPECT_EQ(expected_prefix,
1041 string(delegate.data.data(), expected_prefix.size()));
1042 }
1043 g_main_loop_unref(loop);
1044}
1045} // namespace {}
1046
Darin Petkov9ce452b2010-11-17 14:33:28 -08001047TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001048 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001049 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001050
1051 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1052 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001053
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001054 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001055 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(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001058 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001059 ranges,
1060 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001061 kBigLength - (99 - 25),
1062 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001063}
1064
1065TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001066 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001067 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001068
1069 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1070 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001071
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001072 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001073 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001074 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001075 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001076 ranges,
1077 "abcdefghijabcdefghijabcd",
1078 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001079 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001080}
1081
1082TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001083 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001084 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001085
1086 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1087 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001088
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001089 vector<pair<off_t, off_t> > ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001090 ranges.push_back(make_pair(kBigLength - 2, 0));
1091 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001092 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001093 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001094 ranges,
1095 "ijhij",
1096 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001097 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001098}
1099
1100TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001101 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001102 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001103
1104 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1105 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001106
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001107 vector<pair<off_t, off_t> > ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001108 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001109 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001110 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001111 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001112 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001113 ranges,
1114 "ij",
1115 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001116 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001117 ranges.push_back(make_pair(0, 5));
1118 }
1119}
1120
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001121// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1122// should retry with other proxies listed before giving up.
1123//
1124// (1) successful recovery: The offset fetch will fail twice but succeed with
1125// the third proxy.
1126TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1127 if (!this->test_.IsMulti())
1128 return;
1129
1130 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1131 ASSERT_TRUE(server->started_);
1132
1133 vector<pair<off_t, off_t> > ranges;
1134 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001135 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001136 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001137 LocalServerUrlForPath(server->GetPort(),
1138 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001139 kBigLength)),
1140 ranges,
1141 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1142 kBigLength - (99 - 25),
1143 kHttpResponsePartialContent);
1144}
1145
1146// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1147// fetcher will signal a (failed) completed transfer to the delegate.
1148TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1149 if (!this->test_.IsMulti())
1150 return;
1151
1152 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1153 ASSERT_TRUE(server->started_);
1154
1155 vector<pair<off_t, off_t> > ranges;
1156 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001157 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001158 MultiTest(this->test_.NewLargeFetcher(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001159 LocalServerUrlForPath(server->GetPort(),
1160 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001161 kBigLength)),
1162 ranges,
1163 "abcdefghijabcdefghijabcde", // only received the first chunk
1164 25,
1165 kHttpResponseUndefined);
1166}
1167
1168
1169
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001170namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001171class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001172 public:
1173 virtual void ReceivedBytes(HttpFetcher* fetcher,
1174 const char* bytes, int length) {
1175 ADD_FAILURE();
1176 }
1177 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
1178 EXPECT_FALSE(successful);
1179 g_main_loop_quit(loop_);
1180 }
Darin Petkov9ce452b2010-11-17 14:33:28 -08001181 virtual void TransferTerminated(HttpFetcher* fetcher) {
1182 ADD_FAILURE();
1183 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001184 GMainLoop* loop_;
1185};
1186
1187} // namespace
1188
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001189TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001190 if (this->test_.IsMock() || this->test_.IsMulti())
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001191 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001192
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001193 for (int i = 0; i < 2; i++) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001194 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1195 ASSERT_TRUE(server->started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001196
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001197 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001198 {
1199 BlockedTransferTestDelegate delegate;
1200 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001201
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001202 bool is_allowed = (i != 0);
1203 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
1204 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08001205 fetcher->GetSystemState()->connection_manager());
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001206 EXPECT_CALL(*mock_cm, GetConnectionType(_,_))
1207 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi), Return(true)));
1208 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi))
1209 .WillRepeatedly(Return(is_allowed));
1210 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
1211 .WillRepeatedly(Return(flimflam::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -07001212
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001213 bool is_official_build = (i == 1);
1214 LOG(INFO) << "is_update_allowed_over_connection: " << is_allowed;
1215 LOG(INFO) << "is_official_build: " << is_official_build;
1216 fetcher->SetBuildType(is_official_build);
1217 fetcher->set_delegate(&delegate);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001218
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001219 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001220 {fetcher.get(),
1221 LocalServerUrlForPath(server->GetPort(),
1222 this->test_.SmallUrl(server->GetPort()))};
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001223
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001224 g_timeout_add(0, StartTransfer, &start_xfer_args);
1225 g_main_loop_run(loop);
1226 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001227 g_main_loop_unref(loop);
1228 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001229}
1230
rspangler@google.com49fdf182009-10-10 00:57:34 +00001231} // namespace chromeos_update_engine