blob: d7713c5400d7229d3a2c460813148af928113ef7 [file] [log] [blame]
Mike Frysinger8155d082012-04-06 15:23:18 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
rspangler@google.com49fdf182009-10-10 00:57:34 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07005#include <netinet/in.h>
6#include <netinet/ip.h>
7#include <sys/socket.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +00008#include <unistd.h>
Darin Petkov41c2fcf2010-08-25 13:14:48 -07009
adlr@google.comc98a7ed2009-12-04 18:54:03 +000010#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070011#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000012#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070013
Andrew de los Reyes45168102010-11-22 11:13:50 -080014#include <base/logging.h>
Chris Masoned903c3b2011-05-12 15:35:46 -070015#include <base/memory/scoped_ptr.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070016#include <base/strings/string_util.h>
17#include <base/strings/stringprintf.h>
18#include <base/time/time.h>
Jay Srinivasan43488792012-06-19 00:25:31 -070019#include <chromeos/dbus/service_constants.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080020#include <glib.h>
21#include <gtest/gtest.h>
22
Gilad Arnold5bb4c902014-04-10 12:32:13 -070023#include "update_engine/fake_system_state.h"
Gilad Arnold9bedeb52011-11-17 16:19:57 -080024#include "update_engine/http_common.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000025#include "update_engine/libcurl_http_fetcher.h"
Jay Srinivasan43488792012-06-19 00:25:31 -070026#include "update_engine/mock_connection_manager.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000027#include "update_engine/mock_http_fetcher.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::DoAll;
39using testing::Return;
Alex Deymoc4acdf42014-05-28 21:07:10 -070040using testing::SetArgumentPointee;
41using testing::_;
Jay Srinivasan43488792012-06-19 00:25:31 -070042
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()
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700198 : mock_connection_manager_(&fake_system_state_) {
199 fake_system_state_.set_connection_manager(&mock_connection_manager_);
Jay Srinivasan43488792012-06-19 00:25:31 -0700200 }
Alex Deymoc4acdf42014-05-28 21:07:10 -0700201 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700202
Alex Deymo7984bf02014-04-02 20:41:57 -0700203 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800204 HttpFetcher* NewLargeFetcher() {
205 return NewLargeFetcher(1);
206 }
207
208 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) = 0;
209 HttpFetcher* NewSmallFetcher() {
210 return NewSmallFetcher(1);
211 }
212
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700213 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
214 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
215 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800216
217 virtual bool IsMock() const = 0;
218 virtual bool IsMulti() const = 0;
219
220 virtual void IgnoreServerAborting(HttpServer* server) const {}
221
222 virtual HttpServer *CreateServer() = 0;
223
224 protected:
225 DirectProxyResolver proxy_resolver_;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700226 FakeSystemState fake_system_state_;
Jay Srinivasan43488792012-06-19 00:25:31 -0700227 MockConnectionManager mock_connection_manager_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800228};
229
230class MockHttpFetcherTest : public AnyHttpFetcherTest {
231 public:
232 // Necessary to unhide the definition in the base class.
233 using AnyHttpFetcherTest::NewLargeFetcher;
234 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) {
235 vector<char> big_data(1000000);
236 CHECK(num_proxies > 0);
237 proxy_resolver_.set_num_proxies(num_proxies);
238 return new MockHttpFetcher(
239 big_data.data(),
240 big_data.size(),
241 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
242 }
243
244 // Necessary to unhide the definition in the base class.
245 using AnyHttpFetcherTest::NewSmallFetcher;
246 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) {
247 CHECK(num_proxies > 0);
248 proxy_resolver_.set_num_proxies(num_proxies);
249 return new MockHttpFetcher(
250 "x",
251 1,
252 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
253 }
254
255 virtual bool IsMock() const { return true; }
256 virtual bool IsMulti() const { return false; }
257
258 virtual HttpServer *CreateServer() {
259 return new NullHttpServer;
260 }
261};
262
263class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
264 public:
265 // Necessary to unhide the definition in the base class.
266 using AnyHttpFetcherTest::NewLargeFetcher;
267 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) {
268 CHECK(num_proxies > 0);
269 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes45168102010-11-22 11:13:50 -0800270 LibcurlHttpFetcher *ret = new
Jay Srinivasan08fce042012-06-07 16:31:01 -0700271 LibcurlHttpFetcher(reinterpret_cast<ProxyResolver*>(&proxy_resolver_),
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700272 &fake_system_state_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700273 // Speed up test execution.
274 ret->set_idle_seconds(1);
275 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700276 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000277 return ret;
278 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800279
280 // Necessary to unhide the definition in the base class.
281 using AnyHttpFetcherTest::NewSmallFetcher;
282 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) {
283 return NewLargeFetcher(num_proxies);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000284 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800285
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700286 virtual string BigUrl(in_port_t port) const {
287 return LocalServerUrlForPath(port,
288 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800289 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000290 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700291 virtual string SmallUrl(in_port_t port) const {
292 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000293 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700294 virtual string ErrorUrl(in_port_t port) const {
295 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800296 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800297
298 virtual bool IsMock() const { return false; }
299 virtual bool IsMulti() const { return false; }
300
301 virtual void IgnoreServerAborting(HttpServer* server) const {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700302 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700303 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800304
305 virtual HttpServer *CreateServer() {
306 return new PythonHttpServer;
307 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000308};
309
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800310class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700311 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800312 // Necessary to unhide the definition in the base class.
313 using AnyHttpFetcherTest::NewLargeFetcher;
314 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) {
315 CHECK(num_proxies > 0);
316 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800317 ProxyResolver* resolver =
318 reinterpret_cast<ProxyResolver*>(&proxy_resolver_);
Gilad Arnold7c04e762012-05-23 10:54:02 -0700319 MultiRangeHttpFetcher *ret =
320 new MultiRangeHttpFetcher(
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700321 new LibcurlHttpFetcher(resolver, &fake_system_state_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800322 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800323 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700324 // Speed up test execution.
325 ret->set_idle_seconds(1);
326 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700327 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700328 return ret;
329 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800330
331 // Necessary to unhide the definition in the base class.
332 using AnyHttpFetcherTest::NewSmallFetcher;
333 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) {
334 return NewLargeFetcher(num_proxies);
335 }
336
337 virtual bool IsMulti() const { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700338};
339
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800340
341//
342// Infrastructure for type tests of HTTP fetcher.
343// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
344//
345
346// Fixture class template. We use an explicit constraint to guarantee that it
347// can only be instantiated with an AnyHttpFetcherTest type, see:
348// http://www2.research.att.com/~bs/bs_faq2.html#constraints
349template <typename T>
350class HttpFetcherTest : public ::testing::Test {
351 public:
352 T test_;
353
354 private:
355 static void TypeConstraint(T *a) {
356 AnyHttpFetcherTest *b = a;
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700357 if (b == 0) // Silence compiler warning of unused variable.
358 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800359 }
360};
361
362// Test case types list.
363typedef ::testing::Types<LibcurlHttpFetcherTest,
364 MockHttpFetcherTest,
365 MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000366TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
367
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800368
rspangler@google.com49fdf182009-10-10 00:57:34 +0000369namespace {
370class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000371 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800372 HttpFetcherTestDelegate() :
Gilad Arnold48085ba2011-11-16 09:36:08 -0800373 is_expect_error_(false), times_transfer_complete_called_(0),
374 times_transfer_terminated_called_(0), times_received_bytes_called_(0) {}
375
Alex Deymof9c59992014-04-02 21:16:59 -0700376 virtual void ReceivedBytes(HttpFetcher* /* fetcher */,
377 const char* /* bytes */, int /* length */) {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800378 // Update counters
379 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000380 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800381
rspangler@google.com49fdf182009-10-10 00:57:34 +0000382 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800383 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800384 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800385 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800386 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000387 g_main_loop_quit(loop_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800388
389 // Update counter
390 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000391 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800392
Darin Petkov9ce452b2010-11-17 14:33:28 -0800393 virtual void TransferTerminated(HttpFetcher* fetcher) {
394 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800395 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800396 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800397
rspangler@google.com49fdf182009-10-10 00:57:34 +0000398 GMainLoop* loop_;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800399
400 // Are we expecting an error response? (default: no)
401 bool is_expect_error_;
402
403 // Counters for callback invocations.
404 int times_transfer_complete_called_;
405 int times_transfer_terminated_called_;
406 int times_received_bytes_called_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000407};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000408
409struct StartTransferArgs {
410 HttpFetcher *http_fetcher;
411 string url;
412};
413
414gboolean StartTransfer(gpointer data) {
415 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
416 args->http_fetcher->BeginTransfer(args->url);
417 return FALSE;
418}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000419} // namespace {}
420
421TYPED_TEST(HttpFetcherTest, SimpleTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700422 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000423 {
424 HttpFetcherTestDelegate delegate;
425 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800426 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000427 fetcher->set_delegate(&delegate);
428
Jay Srinivasan43488792012-06-19 00:25:31 -0700429 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800430 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700431 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
432 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
433 SetArgumentPointee<2>(NetworkTethering::kUnknown),
434 Return(true)));
435 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700436 .WillRepeatedly(Return(true));
437 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -0700438 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -0700439
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800440 scoped_ptr<HttpServer> server(this->test_.CreateServer());
441 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000442
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700443 StartTransferArgs start_xfer_args = {
444 fetcher.get(), this->test_.SmallUrl(server->GetPort())};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000445
446 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000447 g_main_loop_run(loop);
448 }
449 g_main_loop_unref(loop);
450}
451
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700452TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700453 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700454 {
455 HttpFetcherTestDelegate delegate;
456 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800457 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700458 fetcher->set_delegate(&delegate);
459
Jay Srinivasan43488792012-06-19 00:25:31 -0700460 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800461 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700462 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
463 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
464 SetArgumentPointee<2>(NetworkTethering::kUnknown),
465 Return(true)));
466 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700467 .WillRepeatedly(Return(true));
468 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
Ben Chanc6007e42013-09-19 23:49:22 -0700469 .WillRepeatedly(Return(shill::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700470
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800471 scoped_ptr<HttpServer> server(this->test_.CreateServer());
472 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700473
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700474 StartTransferArgs start_xfer_args = {
475 fetcher.get(), this->test_.BigUrl(server->GetPort())};
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700476
477 g_timeout_add(0, StartTransfer, &start_xfer_args);
478 g_main_loop_run(loop);
479 }
480 g_main_loop_unref(loop);
481}
482
Gilad Arnold48085ba2011-11-16 09:36:08 -0800483// Issue #9648: when server returns an error HTTP response, the fetcher needs to
484// terminate transfer prematurely, rather than try to process the error payload.
485TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800486 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800487 return;
488 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
489 {
490 HttpFetcherTestDelegate delegate;
491 delegate.loop_ = loop;
492
493 // Delegate should expect an error response.
494 delegate.is_expect_error_ = true;
495
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800496 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800497 fetcher->set_delegate(&delegate);
498
Jay Srinivasan43488792012-06-19 00:25:31 -0700499 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800500 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700501 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
502 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWimax),
503 SetArgumentPointee<2>(NetworkTethering::kUnknown),
504 Return(true)));
505 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWimax, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700506 .WillRepeatedly(Return(true));
507 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWimax))
Ben Chanc6007e42013-09-19 23:49:22 -0700508 .WillRepeatedly(Return(shill::kTypeWimax));
Jay Srinivasan43488792012-06-19 00:25:31 -0700509
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800510 scoped_ptr<HttpServer> server(this->test_.CreateServer());
511 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800512
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800513 StartTransferArgs start_xfer_args = {
514 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700515 this->test_.ErrorUrl(server->GetPort())
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800516 };
Gilad Arnold48085ba2011-11-16 09:36:08 -0800517
518 g_timeout_add(0, StartTransfer, &start_xfer_args);
519 g_main_loop_run(loop);
520
521 // Make sure that no bytes were received.
522 CHECK_EQ(delegate.times_received_bytes_called_, 0);
Mike Frysinger0f9547d2012-02-16 12:11:37 -0500523 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800524
525 // Make sure that transfer completion was signaled once, and no termination
526 // was signaled.
527 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
528 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
529 }
530 g_main_loop_unref(loop);
531}
532
rspangler@google.com49fdf182009-10-10 00:57:34 +0000533namespace {
534class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
535 public:
536 virtual void ReceivedBytes(HttpFetcher* fetcher,
Alex Deymof9c59992014-04-02 21:16:59 -0700537 const char* /* bytes */, int /* length */) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000538 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());
Alex Deymo6ae91202014-03-10 19:21:25 -0700579 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
580 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetCellular),
581 SetArgumentPointee<2>(NetworkTethering::kUnknown),
582 Return(true)));
583 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetCellular, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700584 .WillRepeatedly(Return(true));
585 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetCellular))
Ben Chanc6007e42013-09-19 23:49:22 -0700586 .WillRepeatedly(Return(shill::kTypeCellular));
Jay Srinivasan43488792012-06-19 00:25:31 -0700587
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800588 scoped_ptr<HttpServer> server(this->test_.CreateServer());
589 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800590
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800591 guint callback_id = g_timeout_add(kHttpResponseInternalServerError,
592 UnpausingTimeoutCallback, &delegate);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700593 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000594
595 g_main_loop_run(loop);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800596 g_source_remove(callback_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000597 }
598 g_main_loop_unref(loop);
599}
600
601namespace {
602class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
603 public:
604 virtual void ReceivedBytes(HttpFetcher* fetcher,
605 const char* bytes, int length) {}
606 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800607 ADD_FAILURE(); // We should never get here
rspangler@google.com49fdf182009-10-10 00:57:34 +0000608 g_main_loop_quit(loop_);
609 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800610 virtual void TransferTerminated(HttpFetcher* fetcher) {
611 EXPECT_EQ(fetcher, fetcher_.get());
612 EXPECT_FALSE(once_);
613 EXPECT_TRUE(callback_once_);
614 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700615 // The fetcher could have a callback scheduled on the ProxyResolver that
616 // can fire after this callback. We wait until the end of the test to
617 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800618 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000619 void TerminateTransfer() {
620 CHECK(once_);
621 once_ = false;
622 fetcher_->TerminateTransfer();
623 }
624 void EndLoop() {
625 g_main_loop_quit(loop_);
626 }
627 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800628 bool callback_once_;
629 scoped_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000630 GMainLoop* loop_;
631};
632
633gboolean AbortingTimeoutCallback(gpointer data) {
634 AbortingHttpFetcherTestDelegate *delegate =
635 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
636 if (delegate->once_) {
637 delegate->TerminateTransfer();
638 return TRUE;
639 } else {
640 delegate->EndLoop();
641 return FALSE;
642 }
643}
644} // namespace {}
645
646TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700647 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000648 {
649 AbortingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800650 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000651 delegate.once_ = true;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800652 delegate.callback_once_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000653 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800654 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000655
Jay Srinivasan43488792012-06-19 00:25:31 -0700656 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800657 delegate.fetcher_->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700658 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
659 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
660 SetArgumentPointee<2>(NetworkTethering::kUnknown),
661 Return(true)));
662 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700663 .WillRepeatedly(Return(true));
664 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -0700665 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -0700666
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800667 scoped_ptr<HttpServer> server(this->test_.CreateServer());
668 this->test_.IgnoreServerAborting(server.get());
669 ASSERT_TRUE(server->started_);
670
rspangler@google.com49fdf182009-10-10 00:57:34 +0000671 GSource* timeout_source_;
672 timeout_source_ = g_timeout_source_new(0); // ms
673 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
674 NULL);
675 g_source_attach(timeout_source_, NULL);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700676 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000677
678 g_main_loop_run(loop);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800679 CHECK(!delegate.once_);
680 CHECK(!delegate.callback_once_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000681 g_source_destroy(timeout_source_);
682 }
683 g_main_loop_unref(loop);
684}
685
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000686namespace {
687class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
688 public:
689 virtual void ReceivedBytes(HttpFetcher* fetcher,
690 const char* bytes, int length) {
691 data.append(bytes, length);
692 }
693 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700694 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800695 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000696 g_main_loop_quit(loop_);
697 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800698 virtual void TransferTerminated(HttpFetcher* fetcher) {
699 ADD_FAILURE();
700 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000701 string data;
702 GMainLoop* loop_;
703};
704} // namespace {}
705
706TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800707 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000708 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700709 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000710 {
711 FlakyHttpFetcherTestDelegate delegate;
712 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800713 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000714 fetcher->set_delegate(&delegate);
715
Jay Srinivasan43488792012-06-19 00:25:31 -0700716 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800717 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700718 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
719 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
720 SetArgumentPointee<2>(NetworkTethering::kUnknown),
721 Return(true)));
722 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700723 .WillRepeatedly(Return(true));
724 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -0700725 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -0700726
727
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800728 scoped_ptr<HttpServer> server(this->test_.CreateServer());
729 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000730
731 StartTransferArgs start_xfer_args = {
732 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700733 LocalServerUrlForPath(server->GetPort(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700734 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
735 kFlakyTruncateLength,
736 kFlakySleepEvery,
737 kFlakySleepSecs))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000738 };
739
740 g_timeout_add(0, StartTransfer, &start_xfer_args);
741 g_main_loop_run(loop);
742
743 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800744 ASSERT_EQ(kBigLength, delegate.data.size());
745 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000746 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
747 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
748 }
749 }
750 g_main_loop_unref(loop);
751}
752
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700753namespace {
754class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
755 public:
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700756 FailureHttpFetcherTestDelegate(PythonHttpServer* server)
757 : loop_(NULL),
758 server_(server) {}
759
760 virtual ~FailureHttpFetcherTestDelegate() {
761 if (server_) {
762 LOG(INFO) << "Stopping server in destructor";
763 delete server_;
764 LOG(INFO) << "server stopped";
765 }
766 }
767
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700768 virtual void ReceivedBytes(HttpFetcher* fetcher,
769 const char* bytes, int length) {
770 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700771 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700772 delete server_;
773 LOG(INFO) << "server stopped";
774 server_ = NULL;
775 }
776 }
777 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
778 EXPECT_FALSE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700779 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700780 g_main_loop_quit(loop_);
781 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800782 virtual void TransferTerminated(HttpFetcher* fetcher) {
783 ADD_FAILURE();
784 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700785 GMainLoop* loop_;
786 PythonHttpServer* server_;
787};
788} // namespace {}
789
790
791TYPED_TEST(HttpFetcherTest, FailureTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800792 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700793 return;
794 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
795 {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700796 FailureHttpFetcherTestDelegate delegate(NULL);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700797 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800798 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700799 fetcher->set_delegate(&delegate);
800
Jay Srinivasan43488792012-06-19 00:25:31 -0700801 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800802 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700803 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
804 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
805 SetArgumentPointee<2>(NetworkTethering::kUnknown),
806 Return(true)));
807 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700808 .WillRepeatedly(Return(true));
809 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
Ben Chanc6007e42013-09-19 23:49:22 -0700810 .WillRepeatedly(Return(shill::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700811
812
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700813 StartTransferArgs start_xfer_args = {
814 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700815 LocalServerUrlForPath(0, this->test_.SmallUrl(0))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700816 };
817
818 g_timeout_add(0, StartTransfer, &start_xfer_args);
819 g_main_loop_run(loop);
820
821 // Exiting and testing happens in the delegate
822 }
823 g_main_loop_unref(loop);
824}
825
826TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800827 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700828 return;
829 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
830 {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700831 FailureHttpFetcherTestDelegate delegate(new PythonHttpServer);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700832 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800833 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700834 fetcher->set_delegate(&delegate);
835
Chris Sosa133f8922013-11-06 16:39:16 -0800836 // Don't allow connection to server by denying access over ethernet.
837 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
838 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700839 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
840 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
841 SetArgumentPointee<2>(NetworkTethering::kUnknown),
842 Return(true)));
843 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Chris Sosa133f8922013-11-06 16:39:16 -0800844 .WillRepeatedly(Return(false));
845 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
846 .WillRepeatedly(Return(shill::kTypeEthernet));
847
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700848 StartTransferArgs start_xfer_args = {
849 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700850 LocalServerUrlForPath(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700851 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
852 kFlakyTruncateLength,
853 kFlakySleepEvery,
854 kFlakySleepSecs))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700855 };
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700856 g_timeout_add(0, StartTransfer, &start_xfer_args);
857 g_main_loop_run(loop);
858
859 // Exiting and testing happens in the delegate
860 }
861 g_main_loop_unref(loop);
862}
863
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700864namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800865const HttpResponseCode kRedirectCodes[] = {
866 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
867 kHttpResponseTempRedirect
868};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700869
870class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
871 public:
872 RedirectHttpFetcherTestDelegate(bool expected_successful)
873 : expected_successful_(expected_successful) {}
874 virtual void ReceivedBytes(HttpFetcher* fetcher,
875 const char* bytes, int length) {
876 data.append(bytes, length);
877 }
878 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
879 EXPECT_EQ(expected_successful_, successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700880 if (expected_successful_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800881 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Darin Petkovcb466212010-08-26 09:40:11 -0700882 else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800883 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
884 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700885 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700886 g_main_loop_quit(loop_);
887 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800888 virtual void TransferTerminated(HttpFetcher* fetcher) {
889 ADD_FAILURE();
890 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700891 bool expected_successful_;
892 string data;
893 GMainLoop* loop_;
894};
895
896// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700897void RedirectTest(const HttpServer* server,
898 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700899 const string& url,
900 HttpFetcher* http_fetcher) {
901 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700902 {
903 RedirectHttpFetcherTestDelegate delegate(expected_successful);
904 delegate.loop_ = loop;
905 scoped_ptr<HttpFetcher> fetcher(http_fetcher);
906 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700907
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700908 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800909 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700910 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
911 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
912 SetArgumentPointee<2>(NetworkTethering::kUnknown),
913 Return(true)));
914 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700915 .WillRepeatedly(Return(true));
916 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
Ben Chanc6007e42013-09-19 23:49:22 -0700917 .WillRepeatedly(Return(shill::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700918
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700919 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700920 { fetcher.get(), LocalServerUrlForPath(server->GetPort(), url) };
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700921
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700922 g_timeout_add(0, StartTransfer, &start_xfer_args);
923 g_main_loop_run(loop);
924 if (expected_successful) {
925 // verify the data we get back
926 ASSERT_EQ(kMediumLength, delegate.data.size());
927 for (int i = 0; i < kMediumLength; i += 10) {
928 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
929 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
930 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700931 }
932 }
933 g_main_loop_unref(loop);
934}
935} // namespace {}
936
937TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800938 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700939 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800940
941 scoped_ptr<HttpServer> server(this->test_.CreateServer());
942 ASSERT_TRUE(server->started_);
943
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700944 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800945 const string url = base::StringPrintf("/redirect/%d/download/%d",
946 kRedirectCodes[c],
947 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700948 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700949 }
950}
951
952TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800953 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700954 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800955
956 scoped_ptr<HttpServer> server(this->test_.CreateServer());
957 ASSERT_TRUE(server->started_);
958
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700959 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700960 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700961 url += base::StringPrintf("/redirect/%d",
962 kRedirectCodes[r % arraysize(kRedirectCodes)]);
963 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800964 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700965 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700966}
967
968TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800969 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700970 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800971
972 scoped_ptr<HttpServer> server(this->test_.CreateServer());
973 ASSERT_TRUE(server->started_);
974
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700975 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700976 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700977 url += base::StringPrintf("/redirect/%d",
978 kRedirectCodes[r % arraysize(kRedirectCodes)]);
979 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800980 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700981 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700982}
983
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700984namespace {
985class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
986 public:
987 MultiHttpFetcherTestDelegate(int expected_response_code)
988 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800989
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700990 virtual void ReceivedBytes(HttpFetcher* fetcher,
991 const char* bytes, int length) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800992 EXPECT_EQ(fetcher, fetcher_.get());
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700993 data.append(bytes, length);
994 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800995
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700996 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800997 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800998 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700999 if (expected_response_code_ != 0)
1000 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -08001001 // Destroy the fetcher (because we're allowed to).
1002 fetcher_.reset(NULL);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001003 g_main_loop_quit(loop_);
1004 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001005
Darin Petkov9ce452b2010-11-17 14:33:28 -08001006 virtual void TransferTerminated(HttpFetcher* fetcher) {
1007 ADD_FAILURE();
1008 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001009
Darin Petkov9ce452b2010-11-17 14:33:28 -08001010 scoped_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001011 int expected_response_code_;
1012 string data;
1013 GMainLoop* loop_;
1014};
1015
1016void MultiTest(HttpFetcher* fetcher_in,
1017 const string& url,
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001018 const vector<pair<off_t, off_t> >& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001019 const string& expected_prefix,
1020 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001021 HttpResponseCode expected_response_code) {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001022 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
1023 {
1024 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1025 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -08001026 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001027
1028 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08001029 fetcher_in->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -07001030 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
1031 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
1032 SetArgumentPointee<2>(NetworkTethering::kUnknown),
1033 Return(true)));
1034 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -07001035 .WillRepeatedly(Return(true));
1036 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -07001037 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -07001038
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001039 MultiRangeHttpFetcher* multi_fetcher =
1040 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001041 ASSERT_TRUE(multi_fetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001042 multi_fetcher->ClearRanges();
1043 for (vector<pair<off_t, off_t> >::const_iterator it = ranges.begin(),
1044 e = ranges.end(); it != e; ++it) {
Alex Vakulenko75039d72014-03-25 12:36:28 -07001045 std::string tmp_str = base::StringPrintf("%jd+", it->first);
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001046 if (it->second > 0) {
1047 base::StringAppendF(&tmp_str, "%jd", it->second);
1048 multi_fetcher->AddRange(it->first, it->second);
1049 } else {
1050 base::StringAppendF(&tmp_str, "?");
1051 multi_fetcher->AddRange(it->first);
1052 }
1053 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001054 }
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001055 dynamic_cast<FakeSystemState*>(fetcher_in->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -07001056 ->fake_hardware()->SetIsOfficialBuild(false);
Darin Petkov9ce452b2010-11-17 14:33:28 -08001057 multi_fetcher->set_delegate(&delegate);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001058
Darin Petkov9ce452b2010-11-17 14:33:28 -08001059 StartTransferArgs start_xfer_args = {multi_fetcher, url};
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001060
1061 g_timeout_add(0, StartTransfer, &start_xfer_args);
1062 g_main_loop_run(loop);
1063
1064 EXPECT_EQ(expected_size, delegate.data.size());
1065 EXPECT_EQ(expected_prefix,
1066 string(delegate.data.data(), expected_prefix.size()));
1067 }
1068 g_main_loop_unref(loop);
1069}
1070} // namespace {}
1071
Darin Petkov9ce452b2010-11-17 14:33:28 -08001072TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001073 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001074 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001075
1076 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1077 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001078
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001079 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001080 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001081 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001082 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001083 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001084 ranges,
1085 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001086 kBigLength - (99 - 25),
1087 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001088}
1089
1090TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001091 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001092 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001093
1094 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1095 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001096
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001097 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001098 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001099 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001100 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001101 ranges,
1102 "abcdefghijabcdefghijabcd",
1103 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001104 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001105}
1106
1107TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001108 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001109 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001110
1111 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1112 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001113
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001114 vector<pair<off_t, off_t> > ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001115 ranges.push_back(make_pair(kBigLength - 2, 0));
1116 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001117 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001118 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001119 ranges,
1120 "ijhij",
1121 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001122 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001123}
1124
1125TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001126 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001127 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001128
1129 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1130 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001131
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001132 vector<pair<off_t, off_t> > ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001133 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001134 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001135 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001136 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001137 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001138 ranges,
1139 "ij",
1140 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001141 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001142 ranges.push_back(make_pair(0, 5));
1143 }
1144}
1145
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001146// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1147// should retry with other proxies listed before giving up.
1148//
1149// (1) successful recovery: The offset fetch will fail twice but succeed with
1150// the third proxy.
1151TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1152 if (!this->test_.IsMulti())
1153 return;
1154
1155 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1156 ASSERT_TRUE(server->started_);
1157
1158 vector<pair<off_t, off_t> > ranges;
1159 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001160 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001161 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001162 LocalServerUrlForPath(server->GetPort(),
1163 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001164 kBigLength)),
1165 ranges,
1166 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1167 kBigLength - (99 - 25),
1168 kHttpResponsePartialContent);
1169}
1170
1171// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1172// fetcher will signal a (failed) completed transfer to the delegate.
1173TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1174 if (!this->test_.IsMulti())
1175 return;
1176
1177 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1178 ASSERT_TRUE(server->started_);
1179
1180 vector<pair<off_t, off_t> > ranges;
1181 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001182 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001183 MultiTest(this->test_.NewLargeFetcher(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001184 LocalServerUrlForPath(server->GetPort(),
1185 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001186 kBigLength)),
1187 ranges,
1188 "abcdefghijabcdefghijabcde", // only received the first chunk
1189 25,
1190 kHttpResponseUndefined);
1191}
1192
1193
1194
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001195namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001196class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001197 public:
1198 virtual void ReceivedBytes(HttpFetcher* fetcher,
1199 const char* bytes, int length) {
1200 ADD_FAILURE();
1201 }
1202 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
1203 EXPECT_FALSE(successful);
1204 g_main_loop_quit(loop_);
1205 }
Darin Petkov9ce452b2010-11-17 14:33:28 -08001206 virtual void TransferTerminated(HttpFetcher* fetcher) {
1207 ADD_FAILURE();
1208 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001209 GMainLoop* loop_;
1210};
1211
1212} // namespace
1213
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001214TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001215 if (this->test_.IsMock() || this->test_.IsMulti())
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001216 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001217
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001218 for (int i = 0; i < 2; i++) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001219 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1220 ASSERT_TRUE(server->started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001221
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001222 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001223 {
1224 BlockedTransferTestDelegate delegate;
1225 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001226
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001227 bool is_allowed = (i != 0);
1228 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
1229 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08001230 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -07001231 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
1232 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
1233 SetArgumentPointee<2>(NetworkTethering::kUnknown),
1234 Return(true)));
1235 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001236 .WillRepeatedly(Return(is_allowed));
1237 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -07001238 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -07001239
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001240 bool is_official_build = (i == 1);
1241 LOG(INFO) << "is_update_allowed_over_connection: " << is_allowed;
1242 LOG(INFO) << "is_official_build: " << is_official_build;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001243 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
1244 dynamic_cast<FakeSystemState*>(fetcher->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -07001245 ->fake_hardware()->SetIsOfficialBuild(is_official_build);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001246 fetcher->set_delegate(&delegate);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001247
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001248 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001249 {fetcher.get(),
1250 LocalServerUrlForPath(server->GetPort(),
1251 this->test_.SmallUrl(server->GetPort()))};
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001252
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001253 g_timeout_add(0, StartTransfer, &start_xfer_args);
1254 g_main_loop_run(loop);
1255 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001256 g_main_loop_unref(loop);
1257 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001258}
1259
rspangler@google.com49fdf182009-10-10 00:57:34 +00001260} // namespace chromeos_update_engine