blob: f09bf520640252fcb522ecac7c70e08147b7ff12 [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 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) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070059 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070060 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());
Alex Deymo6ae91202014-03-10 19:21:25 -0700434 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
435 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
436 SetArgumentPointee<2>(NetworkTethering::kUnknown),
437 Return(true)));
438 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700439 .WillRepeatedly(Return(true));
440 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -0700441 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -0700442
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800443 scoped_ptr<HttpServer> server(this->test_.CreateServer());
444 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000445
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700446 StartTransferArgs start_xfer_args = {
447 fetcher.get(), this->test_.SmallUrl(server->GetPort())};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000448
449 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000450 g_main_loop_run(loop);
451 }
452 g_main_loop_unref(loop);
453}
454
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700455TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700456 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700457 {
458 HttpFetcherTestDelegate delegate;
459 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800460 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700461 fetcher->set_delegate(&delegate);
462
Jay Srinivasan43488792012-06-19 00:25:31 -0700463 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800464 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700465 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
466 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
467 SetArgumentPointee<2>(NetworkTethering::kUnknown),
468 Return(true)));
469 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700470 .WillRepeatedly(Return(true));
471 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
Ben Chanc6007e42013-09-19 23:49:22 -0700472 .WillRepeatedly(Return(shill::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700473
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800474 scoped_ptr<HttpServer> server(this->test_.CreateServer());
475 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700476
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700477 StartTransferArgs start_xfer_args = {
478 fetcher.get(), this->test_.BigUrl(server->GetPort())};
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700479
480 g_timeout_add(0, StartTransfer, &start_xfer_args);
481 g_main_loop_run(loop);
482 }
483 g_main_loop_unref(loop);
484}
485
Gilad Arnold48085ba2011-11-16 09:36:08 -0800486// Issue #9648: when server returns an error HTTP response, the fetcher needs to
487// terminate transfer prematurely, rather than try to process the error payload.
488TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800489 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800490 return;
491 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
492 {
493 HttpFetcherTestDelegate delegate;
494 delegate.loop_ = loop;
495
496 // Delegate should expect an error response.
497 delegate.is_expect_error_ = true;
498
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800499 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800500 fetcher->set_delegate(&delegate);
501
Jay Srinivasan43488792012-06-19 00:25:31 -0700502 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800503 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700504 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
505 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWimax),
506 SetArgumentPointee<2>(NetworkTethering::kUnknown),
507 Return(true)));
508 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWimax, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700509 .WillRepeatedly(Return(true));
510 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWimax))
Ben Chanc6007e42013-09-19 23:49:22 -0700511 .WillRepeatedly(Return(shill::kTypeWimax));
Jay Srinivasan43488792012-06-19 00:25:31 -0700512
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800513 scoped_ptr<HttpServer> server(this->test_.CreateServer());
514 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800515
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800516 StartTransferArgs start_xfer_args = {
517 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700518 this->test_.ErrorUrl(server->GetPort())
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800519 };
Gilad Arnold48085ba2011-11-16 09:36:08 -0800520
521 g_timeout_add(0, StartTransfer, &start_xfer_args);
522 g_main_loop_run(loop);
523
524 // Make sure that no bytes were received.
525 CHECK_EQ(delegate.times_received_bytes_called_, 0);
Mike Frysinger0f9547d2012-02-16 12:11:37 -0500526 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800527
528 // Make sure that transfer completion was signaled once, and no termination
529 // was signaled.
530 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
531 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
532 }
533 g_main_loop_unref(loop);
534}
535
rspangler@google.com49fdf182009-10-10 00:57:34 +0000536namespace {
537class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
538 public:
539 virtual void ReceivedBytes(HttpFetcher* fetcher,
540 const char* bytes, int length) {
541 char str[length + 1];
rspangler@google.com49fdf182009-10-10 00:57:34 +0000542 memset(str, 0, length + 1);
543 memcpy(str, bytes, length);
544 CHECK(!paused_);
545 paused_ = true;
546 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000547 }
548 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
549 g_main_loop_quit(loop_);
550 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800551 virtual void TransferTerminated(HttpFetcher* fetcher) {
552 ADD_FAILURE();
553 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000554 void Unpause() {
555 CHECK(paused_);
556 paused_ = false;
557 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000558 }
559 bool paused_;
560 HttpFetcher* fetcher_;
561 GMainLoop* loop_;
562};
563
564gboolean UnpausingTimeoutCallback(gpointer data) {
565 PausingHttpFetcherTestDelegate *delegate =
566 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
567 if (delegate->paused_)
568 delegate->Unpause();
569 return TRUE;
570}
571} // namespace {}
572
573TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700574 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000575 {
576 PausingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800577 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000578 delegate.paused_ = false;
579 delegate.loop_ = loop;
580 delegate.fetcher_ = fetcher.get();
581 fetcher->set_delegate(&delegate);
582
Jay Srinivasan43488792012-06-19 00:25:31 -0700583 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800584 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700585 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
586 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetCellular),
587 SetArgumentPointee<2>(NetworkTethering::kUnknown),
588 Return(true)));
589 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetCellular, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700590 .WillRepeatedly(Return(true));
591 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetCellular))
Ben Chanc6007e42013-09-19 23:49:22 -0700592 .WillRepeatedly(Return(shill::kTypeCellular));
Jay Srinivasan43488792012-06-19 00:25:31 -0700593
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800594 scoped_ptr<HttpServer> server(this->test_.CreateServer());
595 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800596
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800597 guint callback_id = g_timeout_add(kHttpResponseInternalServerError,
598 UnpausingTimeoutCallback, &delegate);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700599 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000600
601 g_main_loop_run(loop);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800602 g_source_remove(callback_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000603 }
604 g_main_loop_unref(loop);
605}
606
607namespace {
608class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
609 public:
610 virtual void ReceivedBytes(HttpFetcher* fetcher,
611 const char* bytes, int length) {}
612 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800613 ADD_FAILURE(); // We should never get here
rspangler@google.com49fdf182009-10-10 00:57:34 +0000614 g_main_loop_quit(loop_);
615 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800616 virtual void TransferTerminated(HttpFetcher* fetcher) {
617 EXPECT_EQ(fetcher, fetcher_.get());
618 EXPECT_FALSE(once_);
619 EXPECT_TRUE(callback_once_);
620 callback_once_ = false;
621 // |fetcher| can be destroyed during this callback.
622 fetcher_.reset(NULL);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800623 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000624 void TerminateTransfer() {
625 CHECK(once_);
626 once_ = false;
627 fetcher_->TerminateTransfer();
628 }
629 void EndLoop() {
630 g_main_loop_quit(loop_);
631 }
632 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800633 bool callback_once_;
634 scoped_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000635 GMainLoop* loop_;
636};
637
638gboolean AbortingTimeoutCallback(gpointer data) {
639 AbortingHttpFetcherTestDelegate *delegate =
640 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
641 if (delegate->once_) {
642 delegate->TerminateTransfer();
643 return TRUE;
644 } else {
645 delegate->EndLoop();
646 return FALSE;
647 }
648}
649} // namespace {}
650
651TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700652 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000653 {
654 AbortingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800655 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000656 delegate.once_ = true;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800657 delegate.callback_once_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000658 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800659 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000660
Jay Srinivasan43488792012-06-19 00:25:31 -0700661 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800662 delegate.fetcher_->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700663 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
664 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
665 SetArgumentPointee<2>(NetworkTethering::kUnknown),
666 Return(true)));
667 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700668 .WillRepeatedly(Return(true));
669 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -0700670 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -0700671
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800672 scoped_ptr<HttpServer> server(this->test_.CreateServer());
673 this->test_.IgnoreServerAborting(server.get());
674 ASSERT_TRUE(server->started_);
675
rspangler@google.com49fdf182009-10-10 00:57:34 +0000676 GSource* timeout_source_;
677 timeout_source_ = g_timeout_source_new(0); // ms
678 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
679 NULL);
680 g_source_attach(timeout_source_, NULL);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700681 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000682
683 g_main_loop_run(loop);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800684 CHECK(!delegate.once_);
685 CHECK(!delegate.callback_once_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000686 g_source_destroy(timeout_source_);
687 }
688 g_main_loop_unref(loop);
689}
690
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000691namespace {
692class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
693 public:
694 virtual void ReceivedBytes(HttpFetcher* fetcher,
695 const char* bytes, int length) {
696 data.append(bytes, length);
697 }
698 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700699 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800700 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000701 g_main_loop_quit(loop_);
702 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800703 virtual void TransferTerminated(HttpFetcher* fetcher) {
704 ADD_FAILURE();
705 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000706 string data;
707 GMainLoop* loop_;
708};
709} // namespace {}
710
711TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800712 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000713 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700714 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000715 {
716 FlakyHttpFetcherTestDelegate delegate;
717 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800718 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000719 fetcher->set_delegate(&delegate);
720
Jay Srinivasan43488792012-06-19 00:25:31 -0700721 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800722 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700723 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
724 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
725 SetArgumentPointee<2>(NetworkTethering::kUnknown),
726 Return(true)));
727 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700728 .WillRepeatedly(Return(true));
729 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -0700730 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -0700731
732
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800733 scoped_ptr<HttpServer> server(this->test_.CreateServer());
734 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000735
736 StartTransferArgs start_xfer_args = {
737 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700738 LocalServerUrlForPath(server->GetPort(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700739 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
740 kFlakyTruncateLength,
741 kFlakySleepEvery,
742 kFlakySleepSecs))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000743 };
744
745 g_timeout_add(0, StartTransfer, &start_xfer_args);
746 g_main_loop_run(loop);
747
748 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800749 ASSERT_EQ(kBigLength, delegate.data.size());
750 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000751 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
752 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
753 }
754 }
755 g_main_loop_unref(loop);
756}
757
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700758namespace {
759class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
760 public:
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700761 FailureHttpFetcherTestDelegate(PythonHttpServer* server)
762 : loop_(NULL),
763 server_(server) {}
764
765 virtual ~FailureHttpFetcherTestDelegate() {
766 if (server_) {
767 LOG(INFO) << "Stopping server in destructor";
768 delete server_;
769 LOG(INFO) << "server stopped";
770 }
771 }
772
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700773 virtual void ReceivedBytes(HttpFetcher* fetcher,
774 const char* bytes, int length) {
775 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700776 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700777 delete server_;
778 LOG(INFO) << "server stopped";
779 server_ = NULL;
780 }
781 }
782 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
783 EXPECT_FALSE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700784 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700785 g_main_loop_quit(loop_);
786 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800787 virtual void TransferTerminated(HttpFetcher* fetcher) {
788 ADD_FAILURE();
789 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700790 GMainLoop* loop_;
791 PythonHttpServer* server_;
792};
793} // namespace {}
794
795
796TYPED_TEST(HttpFetcherTest, FailureTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800797 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700798 return;
799 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
800 {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700801 FailureHttpFetcherTestDelegate delegate(NULL);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700802 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800803 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700804 fetcher->set_delegate(&delegate);
805
Jay Srinivasan43488792012-06-19 00:25:31 -0700806 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800807 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700808 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
809 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
810 SetArgumentPointee<2>(NetworkTethering::kUnknown),
811 Return(true)));
812 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700813 .WillRepeatedly(Return(true));
814 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
Ben Chanc6007e42013-09-19 23:49:22 -0700815 .WillRepeatedly(Return(shill::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700816
817
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700818 StartTransferArgs start_xfer_args = {
819 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700820 LocalServerUrlForPath(0, this->test_.SmallUrl(0))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700821 };
822
823 g_timeout_add(0, StartTransfer, &start_xfer_args);
824 g_main_loop_run(loop);
825
826 // Exiting and testing happens in the delegate
827 }
828 g_main_loop_unref(loop);
829}
830
831TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800832 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700833 return;
834 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
835 {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700836 FailureHttpFetcherTestDelegate delegate(new PythonHttpServer);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700837 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800838 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700839 fetcher->set_delegate(&delegate);
840
Chris Sosa133f8922013-11-06 16:39:16 -0800841 // Don't allow connection to server by denying access over ethernet.
842 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
843 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700844 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
845 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
846 SetArgumentPointee<2>(NetworkTethering::kUnknown),
847 Return(true)));
848 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Chris Sosa133f8922013-11-06 16:39:16 -0800849 .WillRepeatedly(Return(false));
850 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
851 .WillRepeatedly(Return(shill::kTypeEthernet));
852
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700853 StartTransferArgs start_xfer_args = {
854 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700855 LocalServerUrlForPath(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700856 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
857 kFlakyTruncateLength,
858 kFlakySleepEvery,
859 kFlakySleepSecs))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700860 };
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700861 g_timeout_add(0, StartTransfer, &start_xfer_args);
862 g_main_loop_run(loop);
863
864 // Exiting and testing happens in the delegate
865 }
866 g_main_loop_unref(loop);
867}
868
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700869namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800870const HttpResponseCode kRedirectCodes[] = {
871 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
872 kHttpResponseTempRedirect
873};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700874
875class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
876 public:
877 RedirectHttpFetcherTestDelegate(bool expected_successful)
878 : expected_successful_(expected_successful) {}
879 virtual void ReceivedBytes(HttpFetcher* fetcher,
880 const char* bytes, int length) {
881 data.append(bytes, length);
882 }
883 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
884 EXPECT_EQ(expected_successful_, successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700885 if (expected_successful_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800886 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Darin Petkovcb466212010-08-26 09:40:11 -0700887 else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800888 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
889 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700890 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700891 g_main_loop_quit(loop_);
892 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800893 virtual void TransferTerminated(HttpFetcher* fetcher) {
894 ADD_FAILURE();
895 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700896 bool expected_successful_;
897 string data;
898 GMainLoop* loop_;
899};
900
901// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700902void RedirectTest(const HttpServer* server,
903 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700904 const string& url,
905 HttpFetcher* http_fetcher) {
906 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700907 {
908 RedirectHttpFetcherTestDelegate delegate(expected_successful);
909 delegate.loop_ = loop;
910 scoped_ptr<HttpFetcher> fetcher(http_fetcher);
911 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700912
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700913 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800914 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700915 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
916 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
917 SetArgumentPointee<2>(NetworkTethering::kUnknown),
918 Return(true)));
919 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700920 .WillRepeatedly(Return(true));
921 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
Ben Chanc6007e42013-09-19 23:49:22 -0700922 .WillRepeatedly(Return(shill::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700923
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700924 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700925 { fetcher.get(), LocalServerUrlForPath(server->GetPort(), url) };
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700926
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700927 g_timeout_add(0, StartTransfer, &start_xfer_args);
928 g_main_loop_run(loop);
929 if (expected_successful) {
930 // verify the data we get back
931 ASSERT_EQ(kMediumLength, delegate.data.size());
932 for (int i = 0; i < kMediumLength; i += 10) {
933 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
934 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
935 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700936 }
937 }
938 g_main_loop_unref(loop);
939}
940} // namespace {}
941
942TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800943 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700944 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800945
946 scoped_ptr<HttpServer> server(this->test_.CreateServer());
947 ASSERT_TRUE(server->started_);
948
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700949 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800950 const string url = base::StringPrintf("/redirect/%d/download/%d",
951 kRedirectCodes[c],
952 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700953 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700954 }
955}
956
957TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800958 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700959 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800960
961 scoped_ptr<HttpServer> server(this->test_.CreateServer());
962 ASSERT_TRUE(server->started_);
963
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700964 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700965 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700966 url += base::StringPrintf("/redirect/%d",
967 kRedirectCodes[r % arraysize(kRedirectCodes)]);
968 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800969 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700970 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700971}
972
973TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800974 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700975 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800976
977 scoped_ptr<HttpServer> server(this->test_.CreateServer());
978 ASSERT_TRUE(server->started_);
979
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700980 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700981 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700982 url += base::StringPrintf("/redirect/%d",
983 kRedirectCodes[r % arraysize(kRedirectCodes)]);
984 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800985 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700986 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700987}
988
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700989namespace {
990class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
991 public:
992 MultiHttpFetcherTestDelegate(int expected_response_code)
993 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800994
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700995 virtual void ReceivedBytes(HttpFetcher* fetcher,
996 const char* bytes, int length) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800997 EXPECT_EQ(fetcher, fetcher_.get());
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700998 data.append(bytes, length);
999 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001000
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001001 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001002 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001003 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001004 if (expected_response_code_ != 0)
1005 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001006 // Destroy the fetcher (because we're allowed to).
1007 fetcher_.reset(NULL);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001008 g_main_loop_quit(loop_);
1009 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001010
Darin Petkov9ce452b2010-11-17 14:33:28 -08001011 virtual void TransferTerminated(HttpFetcher* fetcher) {
1012 ADD_FAILURE();
1013 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001014
Darin Petkov9ce452b2010-11-17 14:33:28 -08001015 scoped_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001016 int expected_response_code_;
1017 string data;
1018 GMainLoop* loop_;
1019};
1020
1021void MultiTest(HttpFetcher* fetcher_in,
1022 const string& url,
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001023 const vector<pair<off_t, off_t> >& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001024 const string& expected_prefix,
1025 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001026 HttpResponseCode expected_response_code) {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001027 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
1028 {
1029 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1030 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -08001031 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001032
1033 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08001034 fetcher_in->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -07001035 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
1036 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
1037 SetArgumentPointee<2>(NetworkTethering::kUnknown),
1038 Return(true)));
1039 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -07001040 .WillRepeatedly(Return(true));
1041 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -07001042 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -07001043
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001044 MultiRangeHttpFetcher* multi_fetcher =
1045 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001046 ASSERT_TRUE(multi_fetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001047 multi_fetcher->ClearRanges();
1048 for (vector<pair<off_t, off_t> >::const_iterator it = ranges.begin(),
1049 e = ranges.end(); it != e; ++it) {
Alex Vakulenko75039d72014-03-25 12:36:28 -07001050 std::string tmp_str = base::StringPrintf("%jd+", it->first);
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001051 if (it->second > 0) {
1052 base::StringAppendF(&tmp_str, "%jd", it->second);
1053 multi_fetcher->AddRange(it->first, it->second);
1054 } else {
1055 base::StringAppendF(&tmp_str, "?");
1056 multi_fetcher->AddRange(it->first);
1057 }
1058 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001059 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001060 multi_fetcher->SetBuildType(false);
Darin Petkov9ce452b2010-11-17 14:33:28 -08001061 multi_fetcher->set_delegate(&delegate);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001062
Darin Petkov9ce452b2010-11-17 14:33:28 -08001063 StartTransferArgs start_xfer_args = {multi_fetcher, url};
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001064
1065 g_timeout_add(0, StartTransfer, &start_xfer_args);
1066 g_main_loop_run(loop);
1067
1068 EXPECT_EQ(expected_size, delegate.data.size());
1069 EXPECT_EQ(expected_prefix,
1070 string(delegate.data.data(), expected_prefix.size()));
1071 }
1072 g_main_loop_unref(loop);
1073}
1074} // namespace {}
1075
Darin Petkov9ce452b2010-11-17 14:33:28 -08001076TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001077 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001078 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001079
1080 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1081 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001082
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001083 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001084 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001085 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001086 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001087 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001088 ranges,
1089 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001090 kBigLength - (99 - 25),
1091 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001092}
1093
1094TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001095 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001096 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001097
1098 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1099 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001100
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001101 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001102 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001103 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001104 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001105 ranges,
1106 "abcdefghijabcdefghijabcd",
1107 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001108 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001109}
1110
1111TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001112 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001113 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001114
1115 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1116 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001117
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001118 vector<pair<off_t, off_t> > ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001119 ranges.push_back(make_pair(kBigLength - 2, 0));
1120 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001121 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001122 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001123 ranges,
1124 "ijhij",
1125 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001126 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001127}
1128
1129TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001130 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001131 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001132
1133 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1134 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001135
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001136 vector<pair<off_t, off_t> > ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001137 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001138 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001139 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001140 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001141 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001142 ranges,
1143 "ij",
1144 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001145 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001146 ranges.push_back(make_pair(0, 5));
1147 }
1148}
1149
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001150// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1151// should retry with other proxies listed before giving up.
1152//
1153// (1) successful recovery: The offset fetch will fail twice but succeed with
1154// the third proxy.
1155TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1156 if (!this->test_.IsMulti())
1157 return;
1158
1159 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1160 ASSERT_TRUE(server->started_);
1161
1162 vector<pair<off_t, off_t> > ranges;
1163 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001164 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001165 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001166 LocalServerUrlForPath(server->GetPort(),
1167 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001168 kBigLength)),
1169 ranges,
1170 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1171 kBigLength - (99 - 25),
1172 kHttpResponsePartialContent);
1173}
1174
1175// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1176// fetcher will signal a (failed) completed transfer to the delegate.
1177TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1178 if (!this->test_.IsMulti())
1179 return;
1180
1181 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1182 ASSERT_TRUE(server->started_);
1183
1184 vector<pair<off_t, off_t> > ranges;
1185 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001186 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001187 MultiTest(this->test_.NewLargeFetcher(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001188 LocalServerUrlForPath(server->GetPort(),
1189 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001190 kBigLength)),
1191 ranges,
1192 "abcdefghijabcdefghijabcde", // only received the first chunk
1193 25,
1194 kHttpResponseUndefined);
1195}
1196
1197
1198
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001199namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001200class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001201 public:
1202 virtual void ReceivedBytes(HttpFetcher* fetcher,
1203 const char* bytes, int length) {
1204 ADD_FAILURE();
1205 }
1206 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
1207 EXPECT_FALSE(successful);
1208 g_main_loop_quit(loop_);
1209 }
Darin Petkov9ce452b2010-11-17 14:33:28 -08001210 virtual void TransferTerminated(HttpFetcher* fetcher) {
1211 ADD_FAILURE();
1212 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001213 GMainLoop* loop_;
1214};
1215
1216} // namespace
1217
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001218TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001219 if (this->test_.IsMock() || this->test_.IsMulti())
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001220 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001221
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001222 for (int i = 0; i < 2; i++) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001223 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1224 ASSERT_TRUE(server->started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001225
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001226 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001227 {
1228 BlockedTransferTestDelegate delegate;
1229 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001230
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001231 bool is_allowed = (i != 0);
1232 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
1233 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08001234 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -07001235 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
1236 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
1237 SetArgumentPointee<2>(NetworkTethering::kUnknown),
1238 Return(true)));
1239 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001240 .WillRepeatedly(Return(is_allowed));
1241 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -07001242 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -07001243
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001244 bool is_official_build = (i == 1);
1245 LOG(INFO) << "is_update_allowed_over_connection: " << is_allowed;
1246 LOG(INFO) << "is_official_build: " << is_official_build;
1247 fetcher->SetBuildType(is_official_build);
1248 fetcher->set_delegate(&delegate);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001249
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001250 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001251 {fetcher.get(),
1252 LocalServerUrlForPath(server->GetPort(),
1253 this->test_.SmallUrl(server->GetPort()))};
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001254
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001255 g_timeout_add(0, StartTransfer, &start_xfer_args);
1256 g_main_loop_run(loop);
1257 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001258 g_main_loop_unref(loop);
1259 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001260}
1261
rspangler@google.com49fdf182009-10-10 00:57:34 +00001262} // namespace chromeos_update_engine