blob: 91a0d105026b81e6ea06592f1aee5634d0317737 [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
Alex Deymo7984bf02014-04-02 20:41:57 -0700202 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);
Alex Deymo7984bf02014-04-02 20:41:57 -0700275 mock_system_state_.get_fake_hardware()->SetIsOfficialBuild(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);
Alex Deymo7984bf02014-04-02 20:41:57 -0700326 mock_system_state_.get_fake_hardware()->SetIsOfficialBuild(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
Alex Deymof9c59992014-04-02 21:16:59 -0700375 virtual void ReceivedBytes(HttpFetcher* /* fetcher */,
376 const char* /* bytes */, int /* length */) {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800377 // Update counters
378 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000379 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800380
rspangler@google.com49fdf182009-10-10 00:57:34 +0000381 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800382 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800383 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800384 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800385 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000386 g_main_loop_quit(loop_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800387
388 // Update counter
389 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000390 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800391
Darin Petkov9ce452b2010-11-17 14:33:28 -0800392 virtual void TransferTerminated(HttpFetcher* fetcher) {
393 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800394 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800395 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800396
rspangler@google.com49fdf182009-10-10 00:57:34 +0000397 GMainLoop* loop_;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800398
399 // Are we expecting an error response? (default: no)
400 bool is_expect_error_;
401
402 // Counters for callback invocations.
403 int times_transfer_complete_called_;
404 int times_transfer_terminated_called_;
405 int times_received_bytes_called_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000406};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000407
408struct StartTransferArgs {
409 HttpFetcher *http_fetcher;
410 string url;
411};
412
413gboolean StartTransfer(gpointer data) {
414 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
415 args->http_fetcher->BeginTransfer(args->url);
416 return FALSE;
417}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000418} // namespace {}
419
420TYPED_TEST(HttpFetcherTest, SimpleTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700421 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000422 {
423 HttpFetcherTestDelegate delegate;
424 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800425 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000426 fetcher->set_delegate(&delegate);
427
Jay Srinivasan43488792012-06-19 00:25:31 -0700428 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800429 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700430 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
431 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
432 SetArgumentPointee<2>(NetworkTethering::kUnknown),
433 Return(true)));
434 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700435 .WillRepeatedly(Return(true));
436 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -0700437 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -0700438
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800439 scoped_ptr<HttpServer> server(this->test_.CreateServer());
440 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000441
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700442 StartTransferArgs start_xfer_args = {
443 fetcher.get(), this->test_.SmallUrl(server->GetPort())};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000444
445 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000446 g_main_loop_run(loop);
447 }
448 g_main_loop_unref(loop);
449}
450
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700451TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700452 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700453 {
454 HttpFetcherTestDelegate delegate;
455 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800456 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700457 fetcher->set_delegate(&delegate);
458
Jay Srinivasan43488792012-06-19 00:25:31 -0700459 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800460 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700461 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
462 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
463 SetArgumentPointee<2>(NetworkTethering::kUnknown),
464 Return(true)));
465 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700466 .WillRepeatedly(Return(true));
467 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
Ben Chanc6007e42013-09-19 23:49:22 -0700468 .WillRepeatedly(Return(shill::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700469
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800470 scoped_ptr<HttpServer> server(this->test_.CreateServer());
471 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700472
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700473 StartTransferArgs start_xfer_args = {
474 fetcher.get(), this->test_.BigUrl(server->GetPort())};
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700475
476 g_timeout_add(0, StartTransfer, &start_xfer_args);
477 g_main_loop_run(loop);
478 }
479 g_main_loop_unref(loop);
480}
481
Gilad Arnold48085ba2011-11-16 09:36:08 -0800482// Issue #9648: when server returns an error HTTP response, the fetcher needs to
483// terminate transfer prematurely, rather than try to process the error payload.
484TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800485 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800486 return;
487 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
488 {
489 HttpFetcherTestDelegate delegate;
490 delegate.loop_ = loop;
491
492 // Delegate should expect an error response.
493 delegate.is_expect_error_ = true;
494
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800495 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800496 fetcher->set_delegate(&delegate);
497
Jay Srinivasan43488792012-06-19 00:25:31 -0700498 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800499 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700500 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
501 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWimax),
502 SetArgumentPointee<2>(NetworkTethering::kUnknown),
503 Return(true)));
504 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWimax, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700505 .WillRepeatedly(Return(true));
506 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWimax))
Ben Chanc6007e42013-09-19 23:49:22 -0700507 .WillRepeatedly(Return(shill::kTypeWimax));
Jay Srinivasan43488792012-06-19 00:25:31 -0700508
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800509 scoped_ptr<HttpServer> server(this->test_.CreateServer());
510 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800511
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800512 StartTransferArgs start_xfer_args = {
513 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700514 this->test_.ErrorUrl(server->GetPort())
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800515 };
Gilad Arnold48085ba2011-11-16 09:36:08 -0800516
517 g_timeout_add(0, StartTransfer, &start_xfer_args);
518 g_main_loop_run(loop);
519
520 // Make sure that no bytes were received.
521 CHECK_EQ(delegate.times_received_bytes_called_, 0);
Mike Frysinger0f9547d2012-02-16 12:11:37 -0500522 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800523
524 // Make sure that transfer completion was signaled once, and no termination
525 // was signaled.
526 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
527 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
528 }
529 g_main_loop_unref(loop);
530}
531
rspangler@google.com49fdf182009-10-10 00:57:34 +0000532namespace {
533class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
534 public:
535 virtual void ReceivedBytes(HttpFetcher* fetcher,
Alex Deymof9c59992014-04-02 21:16:59 -0700536 const char* /* bytes */, int /* length */) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000537 CHECK(!paused_);
538 paused_ = true;
539 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000540 }
541 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
542 g_main_loop_quit(loop_);
543 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800544 virtual void TransferTerminated(HttpFetcher* fetcher) {
545 ADD_FAILURE();
546 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000547 void Unpause() {
548 CHECK(paused_);
549 paused_ = false;
550 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000551 }
552 bool paused_;
553 HttpFetcher* fetcher_;
554 GMainLoop* loop_;
555};
556
557gboolean UnpausingTimeoutCallback(gpointer data) {
558 PausingHttpFetcherTestDelegate *delegate =
559 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
560 if (delegate->paused_)
561 delegate->Unpause();
562 return TRUE;
563}
564} // namespace {}
565
566TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700567 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000568 {
569 PausingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800570 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000571 delegate.paused_ = false;
572 delegate.loop_ = loop;
573 delegate.fetcher_ = fetcher.get();
574 fetcher->set_delegate(&delegate);
575
Jay Srinivasan43488792012-06-19 00:25:31 -0700576 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800577 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700578 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
579 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetCellular),
580 SetArgumentPointee<2>(NetworkTethering::kUnknown),
581 Return(true)));
582 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetCellular, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700583 .WillRepeatedly(Return(true));
584 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetCellular))
Ben Chanc6007e42013-09-19 23:49:22 -0700585 .WillRepeatedly(Return(shill::kTypeCellular));
Jay Srinivasan43488792012-06-19 00:25:31 -0700586
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800587 scoped_ptr<HttpServer> server(this->test_.CreateServer());
588 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800589
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800590 guint callback_id = g_timeout_add(kHttpResponseInternalServerError,
591 UnpausingTimeoutCallback, &delegate);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700592 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000593
594 g_main_loop_run(loop);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800595 g_source_remove(callback_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000596 }
597 g_main_loop_unref(loop);
598}
599
600namespace {
601class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
602 public:
603 virtual void ReceivedBytes(HttpFetcher* fetcher,
604 const char* bytes, int length) {}
605 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800606 ADD_FAILURE(); // We should never get here
rspangler@google.com49fdf182009-10-10 00:57:34 +0000607 g_main_loop_quit(loop_);
608 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800609 virtual void TransferTerminated(HttpFetcher* fetcher) {
610 EXPECT_EQ(fetcher, fetcher_.get());
611 EXPECT_FALSE(once_);
612 EXPECT_TRUE(callback_once_);
613 callback_once_ = false;
614 // |fetcher| can be destroyed during this callback.
615 fetcher_.reset(NULL);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800616 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000617 void TerminateTransfer() {
618 CHECK(once_);
619 once_ = false;
620 fetcher_->TerminateTransfer();
621 }
622 void EndLoop() {
623 g_main_loop_quit(loop_);
624 }
625 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800626 bool callback_once_;
627 scoped_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000628 GMainLoop* loop_;
629};
630
631gboolean AbortingTimeoutCallback(gpointer data) {
632 AbortingHttpFetcherTestDelegate *delegate =
633 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
634 if (delegate->once_) {
635 delegate->TerminateTransfer();
636 return TRUE;
637 } else {
638 delegate->EndLoop();
639 return FALSE;
640 }
641}
642} // namespace {}
643
644TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700645 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000646 {
647 AbortingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800648 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000649 delegate.once_ = true;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800650 delegate.callback_once_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000651 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800652 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000653
Jay Srinivasan43488792012-06-19 00:25:31 -0700654 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800655 delegate.fetcher_->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700656 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
657 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
658 SetArgumentPointee<2>(NetworkTethering::kUnknown),
659 Return(true)));
660 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700661 .WillRepeatedly(Return(true));
662 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -0700663 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -0700664
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800665 scoped_ptr<HttpServer> server(this->test_.CreateServer());
666 this->test_.IgnoreServerAborting(server.get());
667 ASSERT_TRUE(server->started_);
668
rspangler@google.com49fdf182009-10-10 00:57:34 +0000669 GSource* timeout_source_;
670 timeout_source_ = g_timeout_source_new(0); // ms
671 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
672 NULL);
673 g_source_attach(timeout_source_, NULL);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700674 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000675
676 g_main_loop_run(loop);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800677 CHECK(!delegate.once_);
678 CHECK(!delegate.callback_once_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000679 g_source_destroy(timeout_source_);
680 }
681 g_main_loop_unref(loop);
682}
683
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000684namespace {
685class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
686 public:
687 virtual void ReceivedBytes(HttpFetcher* fetcher,
688 const char* bytes, int length) {
689 data.append(bytes, length);
690 }
691 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700692 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800693 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000694 g_main_loop_quit(loop_);
695 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800696 virtual void TransferTerminated(HttpFetcher* fetcher) {
697 ADD_FAILURE();
698 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000699 string data;
700 GMainLoop* loop_;
701};
702} // namespace {}
703
704TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800705 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000706 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700707 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000708 {
709 FlakyHttpFetcherTestDelegate delegate;
710 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800711 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000712 fetcher->set_delegate(&delegate);
713
Jay Srinivasan43488792012-06-19 00:25:31 -0700714 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800715 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700716 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
717 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
718 SetArgumentPointee<2>(NetworkTethering::kUnknown),
719 Return(true)));
720 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700721 .WillRepeatedly(Return(true));
722 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -0700723 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -0700724
725
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800726 scoped_ptr<HttpServer> server(this->test_.CreateServer());
727 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000728
729 StartTransferArgs start_xfer_args = {
730 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700731 LocalServerUrlForPath(server->GetPort(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700732 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
733 kFlakyTruncateLength,
734 kFlakySleepEvery,
735 kFlakySleepSecs))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000736 };
737
738 g_timeout_add(0, StartTransfer, &start_xfer_args);
739 g_main_loop_run(loop);
740
741 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800742 ASSERT_EQ(kBigLength, delegate.data.size());
743 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000744 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
745 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
746 }
747 }
748 g_main_loop_unref(loop);
749}
750
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700751namespace {
752class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
753 public:
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700754 FailureHttpFetcherTestDelegate(PythonHttpServer* server)
755 : loop_(NULL),
756 server_(server) {}
757
758 virtual ~FailureHttpFetcherTestDelegate() {
759 if (server_) {
760 LOG(INFO) << "Stopping server in destructor";
761 delete server_;
762 LOG(INFO) << "server stopped";
763 }
764 }
765
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700766 virtual void ReceivedBytes(HttpFetcher* fetcher,
767 const char* bytes, int length) {
768 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700769 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700770 delete server_;
771 LOG(INFO) << "server stopped";
772 server_ = NULL;
773 }
774 }
775 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
776 EXPECT_FALSE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700777 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700778 g_main_loop_quit(loop_);
779 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800780 virtual void TransferTerminated(HttpFetcher* fetcher) {
781 ADD_FAILURE();
782 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700783 GMainLoop* loop_;
784 PythonHttpServer* server_;
785};
786} // namespace {}
787
788
789TYPED_TEST(HttpFetcherTest, FailureTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800790 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700791 return;
792 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
793 {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700794 FailureHttpFetcherTestDelegate delegate(NULL);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700795 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800796 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700797 fetcher->set_delegate(&delegate);
798
Jay Srinivasan43488792012-06-19 00:25:31 -0700799 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800800 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700801 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
802 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
803 SetArgumentPointee<2>(NetworkTethering::kUnknown),
804 Return(true)));
805 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Jay Srinivasan43488792012-06-19 00:25:31 -0700806 .WillRepeatedly(Return(true));
807 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
Ben Chanc6007e42013-09-19 23:49:22 -0700808 .WillRepeatedly(Return(shill::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700809
810
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700811 StartTransferArgs start_xfer_args = {
812 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700813 LocalServerUrlForPath(0, this->test_.SmallUrl(0))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700814 };
815
816 g_timeout_add(0, StartTransfer, &start_xfer_args);
817 g_main_loop_run(loop);
818
819 // Exiting and testing happens in the delegate
820 }
821 g_main_loop_unref(loop);
822}
823
824TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800825 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700826 return;
827 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
828 {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700829 FailureHttpFetcherTestDelegate delegate(new PythonHttpServer);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700830 delegate.loop_ = loop;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800831 scoped_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700832 fetcher->set_delegate(&delegate);
833
Chris Sosa133f8922013-11-06 16:39:16 -0800834 // Don't allow connection to server by denying access over ethernet.
835 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
836 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700837 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
838 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
839 SetArgumentPointee<2>(NetworkTethering::kUnknown),
840 Return(true)));
841 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Chris Sosa133f8922013-11-06 16:39:16 -0800842 .WillRepeatedly(Return(false));
843 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
844 .WillRepeatedly(Return(shill::kTypeEthernet));
845
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700846 StartTransferArgs start_xfer_args = {
847 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700848 LocalServerUrlForPath(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700849 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
850 kFlakyTruncateLength,
851 kFlakySleepEvery,
852 kFlakySleepSecs))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700853 };
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700854 g_timeout_add(0, StartTransfer, &start_xfer_args);
855 g_main_loop_run(loop);
856
857 // Exiting and testing happens in the delegate
858 }
859 g_main_loop_unref(loop);
860}
861
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700862namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800863const HttpResponseCode kRedirectCodes[] = {
864 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
865 kHttpResponseTempRedirect
866};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700867
868class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
869 public:
870 RedirectHttpFetcherTestDelegate(bool expected_successful)
871 : expected_successful_(expected_successful) {}
872 virtual void ReceivedBytes(HttpFetcher* fetcher,
873 const char* bytes, int length) {
874 data.append(bytes, length);
875 }
876 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
877 EXPECT_EQ(expected_successful_, successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700878 if (expected_successful_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800879 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Darin Petkovcb466212010-08-26 09:40:11 -0700880 else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800881 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
882 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700883 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700884 g_main_loop_quit(loop_);
885 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800886 virtual void TransferTerminated(HttpFetcher* fetcher) {
887 ADD_FAILURE();
888 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700889 bool expected_successful_;
890 string data;
891 GMainLoop* loop_;
892};
893
894// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700895void RedirectTest(const HttpServer* server,
896 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700897 const string& url,
898 HttpFetcher* http_fetcher) {
899 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700900 {
901 RedirectHttpFetcherTestDelegate delegate(expected_successful);
902 delegate.loop_ = loop;
903 scoped_ptr<HttpFetcher> fetcher(http_fetcher);
904 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700905
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700906 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800907 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -0700908 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
909 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetEthernet),
910 SetArgumentPointee<2>(NetworkTethering::kUnknown),
911 Return(true)));
912 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetEthernet, _))
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700913 .WillRepeatedly(Return(true));
914 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetEthernet))
Ben Chanc6007e42013-09-19 23:49:22 -0700915 .WillRepeatedly(Return(shill::kTypeEthernet));
Jay Srinivasan43488792012-06-19 00:25:31 -0700916
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700917 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700918 { fetcher.get(), LocalServerUrlForPath(server->GetPort(), url) };
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700919
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700920 g_timeout_add(0, StartTransfer, &start_xfer_args);
921 g_main_loop_run(loop);
922 if (expected_successful) {
923 // verify the data we get back
924 ASSERT_EQ(kMediumLength, delegate.data.size());
925 for (int i = 0; i < kMediumLength; i += 10) {
926 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
927 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
928 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700929 }
930 }
931 g_main_loop_unref(loop);
932}
933} // namespace {}
934
935TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800936 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700937 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800938
939 scoped_ptr<HttpServer> server(this->test_.CreateServer());
940 ASSERT_TRUE(server->started_);
941
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700942 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800943 const string url = base::StringPrintf("/redirect/%d/download/%d",
944 kRedirectCodes[c],
945 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700946 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700947 }
948}
949
950TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800951 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700952 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800953
954 scoped_ptr<HttpServer> server(this->test_.CreateServer());
955 ASSERT_TRUE(server->started_);
956
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700957 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700958 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700959 url += base::StringPrintf("/redirect/%d",
960 kRedirectCodes[r % arraysize(kRedirectCodes)]);
961 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800962 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700963 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700964}
965
966TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800967 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700968 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800969
970 scoped_ptr<HttpServer> server(this->test_.CreateServer());
971 ASSERT_TRUE(server->started_);
972
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700973 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700974 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700975 url += base::StringPrintf("/redirect/%d",
976 kRedirectCodes[r % arraysize(kRedirectCodes)]);
977 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800978 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700979 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700980}
981
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700982namespace {
983class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
984 public:
985 MultiHttpFetcherTestDelegate(int expected_response_code)
986 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800987
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700988 virtual void ReceivedBytes(HttpFetcher* fetcher,
989 const char* bytes, int length) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800990 EXPECT_EQ(fetcher, fetcher_.get());
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700991 data.append(bytes, length);
992 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800993
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700994 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800995 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800996 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700997 if (expected_response_code_ != 0)
998 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800999 // Destroy the fetcher (because we're allowed to).
1000 fetcher_.reset(NULL);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001001 g_main_loop_quit(loop_);
1002 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001003
Darin Petkov9ce452b2010-11-17 14:33:28 -08001004 virtual void TransferTerminated(HttpFetcher* fetcher) {
1005 ADD_FAILURE();
1006 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001007
Darin Petkov9ce452b2010-11-17 14:33:28 -08001008 scoped_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001009 int expected_response_code_;
1010 string data;
1011 GMainLoop* loop_;
1012};
1013
1014void MultiTest(HttpFetcher* fetcher_in,
1015 const string& url,
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001016 const vector<pair<off_t, off_t> >& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001017 const string& expected_prefix,
1018 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001019 HttpResponseCode expected_response_code) {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001020 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
1021 {
1022 MultiHttpFetcherTestDelegate delegate(expected_response_code);
1023 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -08001024 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -07001025
1026 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08001027 fetcher_in->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -07001028 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
1029 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
1030 SetArgumentPointee<2>(NetworkTethering::kUnknown),
1031 Return(true)));
1032 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan43488792012-06-19 00:25:31 -07001033 .WillRepeatedly(Return(true));
1034 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -07001035 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -07001036
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001037 MultiRangeHttpFetcher* multi_fetcher =
1038 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001039 ASSERT_TRUE(multi_fetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001040 multi_fetcher->ClearRanges();
1041 for (vector<pair<off_t, off_t> >::const_iterator it = ranges.begin(),
1042 e = ranges.end(); it != e; ++it) {
Alex Vakulenko75039d72014-03-25 12:36:28 -07001043 std::string tmp_str = base::StringPrintf("%jd+", it->first);
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001044 if (it->second > 0) {
1045 base::StringAppendF(&tmp_str, "%jd", it->second);
1046 multi_fetcher->AddRange(it->first, it->second);
1047 } else {
1048 base::StringAppendF(&tmp_str, "?");
1049 multi_fetcher->AddRange(it->first);
1050 }
1051 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001052 }
Alex Deymo7984bf02014-04-02 20:41:57 -07001053 dynamic_cast<MockSystemState*>(fetcher_in->GetSystemState())
1054 ->get_fake_hardware()->SetIsOfficialBuild(false);
Darin Petkov9ce452b2010-11-17 14:33:28 -08001055 multi_fetcher->set_delegate(&delegate);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001056
Darin Petkov9ce452b2010-11-17 14:33:28 -08001057 StartTransferArgs start_xfer_args = {multi_fetcher, url};
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001058
1059 g_timeout_add(0, StartTransfer, &start_xfer_args);
1060 g_main_loop_run(loop);
1061
1062 EXPECT_EQ(expected_size, delegate.data.size());
1063 EXPECT_EQ(expected_prefix,
1064 string(delegate.data.data(), expected_prefix.size()));
1065 }
1066 g_main_loop_unref(loop);
1067}
1068} // namespace {}
1069
Darin Petkov9ce452b2010-11-17 14:33:28 -08001070TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001071 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001072 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001073
1074 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1075 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001076
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001077 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001078 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001079 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001080 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001081 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001082 ranges,
1083 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001084 kBigLength - (99 - 25),
1085 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001086}
1087
1088TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001089 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001090 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001091
1092 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1093 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001094
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001095 vector<pair<off_t, off_t> > ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001096 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001097 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001098 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001099 ranges,
1100 "abcdefghijabcdefghijabcd",
1101 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001102 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001103}
1104
1105TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001106 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001107 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001108
1109 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1110 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001111
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001112 vector<pair<off_t, off_t> > ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001113 ranges.push_back(make_pair(kBigLength - 2, 0));
1114 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001115 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001116 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001117 ranges,
1118 "ijhij",
1119 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001120 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001121}
1122
1123TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001124 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001125 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001126
1127 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1128 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001129
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001130 vector<pair<off_t, off_t> > ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001131 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001132 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001133 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001134 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001135 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001136 ranges,
1137 "ij",
1138 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001139 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001140 ranges.push_back(make_pair(0, 5));
1141 }
1142}
1143
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001144// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1145// should retry with other proxies listed before giving up.
1146//
1147// (1) successful recovery: The offset fetch will fail twice but succeed with
1148// the third proxy.
1149TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1150 if (!this->test_.IsMulti())
1151 return;
1152
1153 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1154 ASSERT_TRUE(server->started_);
1155
1156 vector<pair<off_t, off_t> > ranges;
1157 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001158 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001159 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001160 LocalServerUrlForPath(server->GetPort(),
1161 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001162 kBigLength)),
1163 ranges,
1164 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1165 kBigLength - (99 - 25),
1166 kHttpResponsePartialContent);
1167}
1168
1169// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1170// fetcher will signal a (failed) completed transfer to the delegate.
1171TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1172 if (!this->test_.IsMulti())
1173 return;
1174
1175 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1176 ASSERT_TRUE(server->started_);
1177
1178 vector<pair<off_t, off_t> > ranges;
1179 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001180 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001181 MultiTest(this->test_.NewLargeFetcher(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001182 LocalServerUrlForPath(server->GetPort(),
1183 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001184 kBigLength)),
1185 ranges,
1186 "abcdefghijabcdefghijabcde", // only received the first chunk
1187 25,
1188 kHttpResponseUndefined);
1189}
1190
1191
1192
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001193namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001194class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001195 public:
1196 virtual void ReceivedBytes(HttpFetcher* fetcher,
1197 const char* bytes, int length) {
1198 ADD_FAILURE();
1199 }
1200 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
1201 EXPECT_FALSE(successful);
1202 g_main_loop_quit(loop_);
1203 }
Darin Petkov9ce452b2010-11-17 14:33:28 -08001204 virtual void TransferTerminated(HttpFetcher* fetcher) {
1205 ADD_FAILURE();
1206 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001207 GMainLoop* loop_;
1208};
1209
1210} // namespace
1211
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001212TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001213 if (this->test_.IsMock() || this->test_.IsMulti())
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001214 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001215
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001216 for (int i = 0; i < 2; i++) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001217 scoped_ptr<HttpServer> server(this->test_.CreateServer());
1218 ASSERT_TRUE(server->started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001219
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001220 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001221 {
1222 BlockedTransferTestDelegate delegate;
1223 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001224
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001225 bool is_allowed = (i != 0);
1226 scoped_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
1227 MockConnectionManager* mock_cm = dynamic_cast<MockConnectionManager*>(
Jay Srinivasan6f6ea002012-12-14 11:26:28 -08001228 fetcher->GetSystemState()->connection_manager());
Alex Deymo6ae91202014-03-10 19:21:25 -07001229 EXPECT_CALL(*mock_cm, GetConnectionProperties(_,_,_))
1230 .WillRepeatedly(DoAll(SetArgumentPointee<1>(kNetWifi),
1231 SetArgumentPointee<2>(NetworkTethering::kUnknown),
1232 Return(true)));
1233 EXPECT_CALL(*mock_cm, IsUpdateAllowedOver(kNetWifi, _))
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001234 .WillRepeatedly(Return(is_allowed));
1235 EXPECT_CALL(*mock_cm, StringForConnectionType(kNetWifi))
Ben Chanc6007e42013-09-19 23:49:22 -07001236 .WillRepeatedly(Return(shill::kTypeWifi));
Jay Srinivasan43488792012-06-19 00:25:31 -07001237
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001238 bool is_official_build = (i == 1);
1239 LOG(INFO) << "is_update_allowed_over_connection: " << is_allowed;
1240 LOG(INFO) << "is_official_build: " << is_official_build;
Alex Deymo7984bf02014-04-02 20:41:57 -07001241 // NewLargeFetcher creates the HttpFetcher* with a MockSystemState.
1242 dynamic_cast<MockSystemState*>(fetcher->GetSystemState())
1243 ->get_fake_hardware()->SetIsOfficialBuild(is_official_build);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001244 fetcher->set_delegate(&delegate);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001245
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001246 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001247 {fetcher.get(),
1248 LocalServerUrlForPath(server->GetPort(),
1249 this->test_.SmallUrl(server->GetPort()))};
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001250
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001251 g_timeout_add(0, StartTransfer, &start_xfer_args);
1252 g_main_loop_run(loop);
1253 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001254 g_main_loop_unref(loop);
1255 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001256}
1257
rspangler@google.com49fdf182009-10-10 00:57:34 +00001258} // namespace chromeos_update_engine