blob: 0e67ce993e252b155a1787b0dd9de1ead3c7ad4a [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
Ben Chan02f7c1d2014-10-18 15:18:02 -070010#include <memory>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000011#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070012#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000013#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070014
Andrew de los Reyes45168102010-11-22 11:13:50 -080015#include <base/logging.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070016#include <base/strings/string_util.h>
17#include <base/strings/stringprintf.h>
18#include <base/time/time.h>
Jay Srinivasan43488792012-06-19 00:25:31 -070019#include <chromeos/dbus/service_constants.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080020#include <glib.h>
21#include <gtest/gtest.h>
22
Gilad Arnold5bb4c902014-04-10 12:32:13 -070023#include "update_engine/fake_system_state.h"
Gilad Arnold9bedeb52011-11-17 16:19:57 -080024#include "update_engine/http_common.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000025#include "update_engine/libcurl_http_fetcher.h"
26#include "update_engine/mock_http_fetcher.h"
Andrew de los Reyes819fef22010-12-17 11:33:58 -080027#include "update_engine/multi_range_http_fetcher.h"
Andrew de los Reyes45168102010-11-22 11:13:50 -080028#include "update_engine/proxy_resolver.h"
Jay Srinivasan08fce042012-06-07 16:31:01 -070029#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000030
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070031using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080032using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000033using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070034using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000035using 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"),
Alex Vakulenko88b591f2014-08-28 16:48:57 -070099 nullptr
100 };
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700101 GError *err;
102 gint server_stdout = -1;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700103 if (!g_spawn_async_with_pipes(nullptr, argv, nullptr,
104 G_SPAWN_DO_NOT_REAP_CHILD, nullptr, nullptr,
105 &pid_, nullptr, &server_stdout, nullptr,
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700106 &err)) {
107 LOG(ERROR) << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000108 return;
109 }
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700110 CHECK_GT(pid_, 0);
111 CHECK_GE(server_stdout, 0);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700112 LOG(INFO) << "started http server with pid " << pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700113
114 // Wait for server to begin accepting connections, obtain its port.
115 char line[80];
116 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
117 CHECK_GT(sizeof(line), listening_msg_prefix_len);
118 int line_len = read(server_stdout, line, sizeof(line) - 1);
119 if (line_len <= static_cast<int>(listening_msg_prefix_len)) {
120 if (line_len < 0) {
121 LOG(ERROR) << "error reading http server stdout: "
122 << strerror(errno);
123 } else {
124 LOG(ERROR) << "server output too short";
125 }
126 Terminate(true);
127 return;
128 }
129
130 line[line_len] = '\0';
131 CHECK_EQ(strstr(line, kServerListeningMsgPrefix), line);
132 const char* listening_port_str = line + listening_msg_prefix_len;
133 char* end_ptr;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700134 long raw_port = strtol(listening_port_str, // NOLINT(runtime/int)
135 &end_ptr, 10);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700136 CHECK(!*end_ptr || *end_ptr == '\n');
137 port_ = static_cast<in_port_t>(raw_port);
138 CHECK_GT(port_, 0);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700139 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700140 LOG(INFO) << "server running, listening on port " << port_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700141 LOG(INFO) << "gdb attach now!";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000142 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800143
rspangler@google.com49fdf182009-10-10 00:57:34 +0000144 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700145 // If there's no process, do nothing.
146 if (pid_ == -1)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000147 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700148
149 // If server is responsive, request that it gracefully terminate.
150 bool do_kill = false;
151 if (started_) {
152 LOG(INFO) << "running wget to exit";
153 if (system((string("wget -t 1 --output-document=/dev/null ") +
154 LocalServerUrlForPath(port_, "/quitquitquit")).c_str())) {
155 LOG(WARNING) << "wget failed, resorting to brute force";
156 do_kill = true;
157 }
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700158 }
159
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700160 // Server not responding or wget failed, kill the process.
161 Terminate(do_kill);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000162 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800163
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700164 virtual in_port_t GetPort() const {
165 return port_;
166 }
167
168 private:
169 void Terminate(bool do_kill) {
170 ASSERT_GT(pid_, 0);
171
172 if (do_kill) {
173 LOG(INFO) << "terminating (SIGKILL) server process with pid " << pid_;
174 kill(pid_, SIGKILL);
175 }
176
177 LOG(INFO) << "waiting for http server with pid " << pid_ << " to terminate";
178 int status;
179 pid_t killed_pid = waitpid(pid_, &status, 0);
180 ASSERT_EQ(killed_pid, pid_);
181 LOG(INFO) << "http server with pid " << pid_
182 << " terminated with status " << status;
183 pid_ = -1;
184 }
185
186 static const char* kServerListeningMsgPrefix;
187
rspangler@google.com49fdf182009-10-10 00:57:34 +0000188 GPid pid_;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700189 in_port_t port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000190};
191
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700192const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
193
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800194//
195// Class hierarchy for HTTP fetcher test wrappers.
196//
197
198class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000199 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700200 AnyHttpFetcherTest() {}
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_;
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);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700235 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800236 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) {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700246 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800247 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) {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700267 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800268 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_),
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700271 &fake_system_state_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700272 // Speed up test execution.
273 ret->set_idle_seconds(1);
274 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700275 fake_system_state_.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) {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700314 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800315 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(
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700320 new LibcurlHttpFetcher(resolver, &fake_system_state_));
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);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700326 fake_system_state_.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;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700356 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700357 *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}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700418} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000419
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;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700425 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000426 fetcher->set_delegate(&delegate);
427
Ben Chan02f7c1d2014-10-18 15:18:02 -0700428 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800429 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000430
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700431 StartTransferArgs start_xfer_args = {
432 fetcher.get(), this->test_.SmallUrl(server->GetPort())};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000433
434 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000435 g_main_loop_run(loop);
436 }
437 g_main_loop_unref(loop);
438}
439
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700440TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700441 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700442 {
443 HttpFetcherTestDelegate delegate;
444 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700445 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700446 fetcher->set_delegate(&delegate);
447
Ben Chan02f7c1d2014-10-18 15:18:02 -0700448 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800449 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700450
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700451 StartTransferArgs start_xfer_args = {
452 fetcher.get(), this->test_.BigUrl(server->GetPort())};
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700453
454 g_timeout_add(0, StartTransfer, &start_xfer_args);
455 g_main_loop_run(loop);
456 }
457 g_main_loop_unref(loop);
458}
459
Gilad Arnold48085ba2011-11-16 09:36:08 -0800460// Issue #9648: when server returns an error HTTP response, the fetcher needs to
461// terminate transfer prematurely, rather than try to process the error payload.
462TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800463 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800464 return;
465 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
466 {
467 HttpFetcherTestDelegate delegate;
468 delegate.loop_ = loop;
469
470 // Delegate should expect an error response.
471 delegate.is_expect_error_ = true;
472
Ben Chan02f7c1d2014-10-18 15:18:02 -0700473 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800474 fetcher->set_delegate(&delegate);
475
Ben Chan02f7c1d2014-10-18 15:18:02 -0700476 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800477 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800478
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800479 StartTransferArgs start_xfer_args = {
480 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700481 this->test_.ErrorUrl(server->GetPort())
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800482 };
Gilad Arnold48085ba2011-11-16 09:36:08 -0800483
484 g_timeout_add(0, StartTransfer, &start_xfer_args);
485 g_main_loop_run(loop);
486
487 // Make sure that no bytes were received.
488 CHECK_EQ(delegate.times_received_bytes_called_, 0);
Mike Frysinger0f9547d2012-02-16 12:11:37 -0500489 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800490
491 // Make sure that transfer completion was signaled once, and no termination
492 // was signaled.
493 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
494 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
495 }
496 g_main_loop_unref(loop);
497}
498
rspangler@google.com49fdf182009-10-10 00:57:34 +0000499namespace {
500class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
501 public:
502 virtual void ReceivedBytes(HttpFetcher* fetcher,
Alex Deymof9c59992014-04-02 21:16:59 -0700503 const char* /* bytes */, int /* length */) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000504 CHECK(!paused_);
505 paused_ = true;
506 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000507 }
508 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
509 g_main_loop_quit(loop_);
510 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800511 virtual void TransferTerminated(HttpFetcher* fetcher) {
512 ADD_FAILURE();
513 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000514 void Unpause() {
515 CHECK(paused_);
516 paused_ = false;
517 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000518 }
519 bool paused_;
520 HttpFetcher* fetcher_;
521 GMainLoop* loop_;
522};
523
524gboolean UnpausingTimeoutCallback(gpointer data) {
525 PausingHttpFetcherTestDelegate *delegate =
526 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
527 if (delegate->paused_)
528 delegate->Unpause();
529 return TRUE;
530}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700531} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000532
533TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700534 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000535 {
536 PausingHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700537 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000538 delegate.paused_ = false;
539 delegate.loop_ = loop;
540 delegate.fetcher_ = fetcher.get();
541 fetcher->set_delegate(&delegate);
542
Ben Chan02f7c1d2014-10-18 15:18:02 -0700543 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800544 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800545
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800546 guint callback_id = g_timeout_add(kHttpResponseInternalServerError,
547 UnpausingTimeoutCallback, &delegate);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700548 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000549
550 g_main_loop_run(loop);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800551 g_source_remove(callback_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000552 }
553 g_main_loop_unref(loop);
554}
555
556namespace {
557class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
558 public:
559 virtual void ReceivedBytes(HttpFetcher* fetcher,
560 const char* bytes, int length) {}
561 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800562 ADD_FAILURE(); // We should never get here
rspangler@google.com49fdf182009-10-10 00:57:34 +0000563 g_main_loop_quit(loop_);
564 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800565 virtual void TransferTerminated(HttpFetcher* fetcher) {
566 EXPECT_EQ(fetcher, fetcher_.get());
567 EXPECT_FALSE(once_);
568 EXPECT_TRUE(callback_once_);
569 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700570 // The fetcher could have a callback scheduled on the ProxyResolver that
571 // can fire after this callback. We wait until the end of the test to
572 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800573 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000574 void TerminateTransfer() {
575 CHECK(once_);
576 once_ = false;
577 fetcher_->TerminateTransfer();
578 }
579 void EndLoop() {
580 g_main_loop_quit(loop_);
581 }
582 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800583 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700584 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000585 GMainLoop* loop_;
586};
587
588gboolean AbortingTimeoutCallback(gpointer data) {
589 AbortingHttpFetcherTestDelegate *delegate =
590 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
591 if (delegate->once_) {
592 delegate->TerminateTransfer();
593 return TRUE;
594 } else {
595 delegate->EndLoop();
596 return FALSE;
597 }
598}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700599} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000600
601TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700602 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000603 {
604 AbortingHttpFetcherTestDelegate delegate;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800605 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000606 delegate.once_ = true;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800607 delegate.callback_once_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000608 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800609 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000610
Ben Chan02f7c1d2014-10-18 15:18:02 -0700611 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800612 this->test_.IgnoreServerAborting(server.get());
613 ASSERT_TRUE(server->started_);
614
rspangler@google.com49fdf182009-10-10 00:57:34 +0000615 GSource* timeout_source_;
616 timeout_source_ = g_timeout_source_new(0); // ms
617 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700618 nullptr);
619 g_source_attach(timeout_source_, nullptr);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700620 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000621
622 g_main_loop_run(loop);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800623 CHECK(!delegate.once_);
624 CHECK(!delegate.callback_once_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000625 g_source_destroy(timeout_source_);
626 }
627 g_main_loop_unref(loop);
628}
629
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000630namespace {
631class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
632 public:
633 virtual void ReceivedBytes(HttpFetcher* fetcher,
634 const char* bytes, int length) {
635 data.append(bytes, length);
636 }
637 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700638 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800639 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000640 g_main_loop_quit(loop_);
641 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800642 virtual void TransferTerminated(HttpFetcher* fetcher) {
643 ADD_FAILURE();
644 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000645 string data;
646 GMainLoop* loop_;
647};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700648} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000649
650TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800651 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000652 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700653 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000654 {
655 FlakyHttpFetcherTestDelegate delegate;
656 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700657 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000658 fetcher->set_delegate(&delegate);
659
Ben Chan02f7c1d2014-10-18 15:18:02 -0700660 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800661 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000662
663 StartTransferArgs start_xfer_args = {
664 fetcher.get(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700665 LocalServerUrlForPath(server->GetPort(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700666 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
667 kFlakyTruncateLength,
668 kFlakySleepEvery,
669 kFlakySleepSecs))
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000670 };
671
672 g_timeout_add(0, StartTransfer, &start_xfer_args);
673 g_main_loop_run(loop);
674
675 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800676 ASSERT_EQ(kBigLength, delegate.data.size());
677 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000678 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
679 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
680 }
681 }
682 g_main_loop_unref(loop);
683}
684
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700685namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700686// This delegate kills the server attached to it after receiving any bytes.
687// This can be used for testing what happens when you try to fetch data and
688// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700689class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
690 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700691 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700692 : loop_(nullptr),
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700693 server_(server) {}
694
695 virtual ~FailureHttpFetcherTestDelegate() {
696 if (server_) {
697 LOG(INFO) << "Stopping server in destructor";
698 delete server_;
699 LOG(INFO) << "server stopped";
700 }
701 }
702
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700703 virtual void ReceivedBytes(HttpFetcher* fetcher,
704 const char* bytes, int length) {
705 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700706 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700707 delete server_;
708 LOG(INFO) << "server stopped";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700709 server_ = nullptr;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700710 }
711 }
712 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
713 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700714 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700715 g_main_loop_quit(loop_);
716 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800717 virtual void TransferTerminated(HttpFetcher* fetcher) {
718 ADD_FAILURE();
719 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700720 GMainLoop* loop_;
721 PythonHttpServer* server_;
722};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700723} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700724
725
726TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700727 // This test ensures that a fetcher responds correctly when a server isn't
728 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800729 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700730 return;
731 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
732 {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700733 FailureHttpFetcherTestDelegate delegate(nullptr);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700734 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700735 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700736 fetcher->set_delegate(&delegate);
737
738 StartTransferArgs start_xfer_args = {
739 fetcher.get(),
Chris Sosa0a364bb2014-06-10 18:18:24 -0700740 "http://host_doesnt_exist99999999",
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700741 };
742
743 g_timeout_add(0, StartTransfer, &start_xfer_args);
744 g_main_loop_run(loop);
745
746 // Exiting and testing happens in the delegate
747 }
748 g_main_loop_unref(loop);
749}
750
751TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700752 // This test starts a new http server and kills it after receiving its first
753 // set of bytes. It test whether or not our fetcher eventually gives up on
754 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800755 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700756 return;
757 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
758 {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700759 PythonHttpServer* server = new PythonHttpServer();
760 int port = server->GetPort();
761 ASSERT_TRUE(server->started_);
762
763 // Handles destruction and claims ownership.
764 FailureHttpFetcherTestDelegate delegate(server);
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700765 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700766 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700767 fetcher->set_delegate(&delegate);
768
769 StartTransferArgs start_xfer_args = {
770 fetcher.get(),
Chris Sosa0a364bb2014-06-10 18:18:24 -0700771 LocalServerUrlForPath(port,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700772 base::StringPrintf("/flaky/%d/%d/%d/%d", kBigLength,
773 kFlakyTruncateLength,
774 kFlakySleepEvery,
775 kFlakySleepSecs))
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700776 };
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700777 g_timeout_add(0, StartTransfer, &start_xfer_args);
778 g_main_loop_run(loop);
779
780 // Exiting and testing happens in the delegate
781 }
782 g_main_loop_unref(loop);
783}
784
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700785namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800786const HttpResponseCode kRedirectCodes[] = {
787 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
788 kHttpResponseTempRedirect
789};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700790
791class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
792 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700793 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700794 : expected_successful_(expected_successful) {}
795 virtual void ReceivedBytes(HttpFetcher* fetcher,
796 const char* bytes, int length) {
797 data.append(bytes, length);
798 }
799 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
800 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700801 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800802 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700803 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800804 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
805 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700806 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700807 g_main_loop_quit(loop_);
808 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800809 virtual void TransferTerminated(HttpFetcher* fetcher) {
810 ADD_FAILURE();
811 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700812 bool expected_successful_;
813 string data;
814 GMainLoop* loop_;
815};
816
817// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700818void RedirectTest(const HttpServer* server,
819 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700820 const string& url,
821 HttpFetcher* http_fetcher) {
822 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700823 {
824 RedirectHttpFetcherTestDelegate delegate(expected_successful);
825 delegate.loop_ = loop;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700826 unique_ptr<HttpFetcher> fetcher(http_fetcher);
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700827 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700828
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700829 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700830 { fetcher.get(), LocalServerUrlForPath(server->GetPort(), url) };
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700831
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700832 g_timeout_add(0, StartTransfer, &start_xfer_args);
833 g_main_loop_run(loop);
834 if (expected_successful) {
835 // verify the data we get back
836 ASSERT_EQ(kMediumLength, delegate.data.size());
837 for (int i = 0; i < kMediumLength; i += 10) {
838 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
839 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
840 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700841 }
842 }
843 g_main_loop_unref(loop);
844}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700845} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700846
847TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800848 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700849 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800850
Ben Chan02f7c1d2014-10-18 15:18:02 -0700851 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800852 ASSERT_TRUE(server->started_);
853
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700854 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800855 const string url = base::StringPrintf("/redirect/%d/download/%d",
856 kRedirectCodes[c],
857 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700858 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700859 }
860}
861
862TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800863 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700864 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800865
Ben Chan02f7c1d2014-10-18 15:18:02 -0700866 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800867 ASSERT_TRUE(server->started_);
868
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700869 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700870 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700871 url += base::StringPrintf("/redirect/%d",
872 kRedirectCodes[r % arraysize(kRedirectCodes)]);
873 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800874 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700875 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700876}
877
878TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800879 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700880 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800881
Ben Chan02f7c1d2014-10-18 15:18:02 -0700882 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800883 ASSERT_TRUE(server->started_);
884
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700885 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700886 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700887 url += base::StringPrintf("/redirect/%d",
888 kRedirectCodes[r % arraysize(kRedirectCodes)]);
889 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800890 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700891 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700892}
893
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700894namespace {
895class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
896 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700897 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700898 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800899
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700900 virtual void ReceivedBytes(HttpFetcher* fetcher,
901 const char* bytes, int length) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800902 EXPECT_EQ(fetcher, fetcher_.get());
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700903 data.append(bytes, length);
904 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800905
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700906 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800907 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800908 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700909 if (expected_response_code_ != 0)
910 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800911 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700912 fetcher_.reset(nullptr);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700913 g_main_loop_quit(loop_);
914 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800915
Darin Petkov9ce452b2010-11-17 14:33:28 -0800916 virtual void TransferTerminated(HttpFetcher* fetcher) {
917 ADD_FAILURE();
918 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800919
Ben Chan02f7c1d2014-10-18 15:18:02 -0700920 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700921 int expected_response_code_;
922 string data;
923 GMainLoop* loop_;
924};
925
926void MultiTest(HttpFetcher* fetcher_in,
927 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -0700928 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700929 const string& expected_prefix,
930 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800931 HttpResponseCode expected_response_code) {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700932 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
933 {
934 MultiHttpFetcherTestDelegate delegate(expected_response_code);
935 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800936 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -0700937
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800938 MultiRangeHttpFetcher* multi_fetcher =
939 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700940 ASSERT_TRUE(multi_fetcher);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800941 multi_fetcher->ClearRanges();
Ben Chanf9cb98c2014-09-21 18:31:30 -0700942 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800943 e = ranges.end(); it != e; ++it) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700944 std::string tmp_str = base::StringPrintf("%jd+", it->first);
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800945 if (it->second > 0) {
946 base::StringAppendF(&tmp_str, "%jd", it->second);
947 multi_fetcher->AddRange(it->first, it->second);
948 } else {
949 base::StringAppendF(&tmp_str, "?");
950 multi_fetcher->AddRange(it->first);
951 }
952 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800953 }
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700954 dynamic_cast<FakeSystemState*>(fetcher_in->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -0700955 ->fake_hardware()->SetIsOfficialBuild(false);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800956 multi_fetcher->set_delegate(&delegate);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700957
Darin Petkov9ce452b2010-11-17 14:33:28 -0800958 StartTransferArgs start_xfer_args = {multi_fetcher, url};
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700959
960 g_timeout_add(0, StartTransfer, &start_xfer_args);
961 g_main_loop_run(loop);
962
963 EXPECT_EQ(expected_size, delegate.data.size());
964 EXPECT_EQ(expected_prefix,
965 string(delegate.data.data(), expected_prefix.size()));
966 }
967 g_main_loop_unref(loop);
968}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700969} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700970
Darin Petkov9ce452b2010-11-17 14:33:28 -0800971TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800972 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700973 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800974
Ben Chan02f7c1d2014-10-18 15:18:02 -0700975 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800976 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700977
Ben Chanf9cb98c2014-09-21 18:31:30 -0700978 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700979 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800980 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800981 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700982 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700983 ranges,
984 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800985 kBigLength - (99 - 25),
986 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700987}
988
989TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800990 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700991 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800992
Ben Chan02f7c1d2014-10-18 15:18:02 -0700993 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800994 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700995
Ben Chanf9cb98c2014-09-21 18:31:30 -0700996 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700997 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800998 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700999 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001000 ranges,
1001 "abcdefghijabcdefghijabcd",
1002 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001003 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001004}
1005
1006TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001007 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001008 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001009
Ben Chan02f7c1d2014-10-18 15:18:02 -07001010 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001011 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001012
Ben Chanf9cb98c2014-09-21 18:31:30 -07001013 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001014 ranges.push_back(make_pair(kBigLength - 2, 0));
1015 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001016 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001017 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001018 ranges,
1019 "ijhij",
1020 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001021 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001022}
1023
1024TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001025 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001026 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001027
Ben Chan02f7c1d2014-10-18 15:18:02 -07001028 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001029 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001030
Ben Chanf9cb98c2014-09-21 18:31:30 -07001031 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001032 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001033 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -08001034 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001035 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001036 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001037 ranges,
1038 "ij",
1039 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001040 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07001041 ranges.push_back(make_pair(0, 5));
1042 }
1043}
1044
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001045// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1046// should retry with other proxies listed before giving up.
1047//
1048// (1) successful recovery: The offset fetch will fail twice but succeed with
1049// the third proxy.
1050TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1051 if (!this->test_.IsMulti())
1052 return;
1053
Ben Chan02f7c1d2014-10-18 15:18:02 -07001054 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001055 ASSERT_TRUE(server->started_);
1056
Ben Chanf9cb98c2014-09-21 18:31:30 -07001057 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001058 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001059 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001060 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001061 LocalServerUrlForPath(server->GetPort(),
1062 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001063 kBigLength)),
1064 ranges,
1065 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1066 kBigLength - (99 - 25),
1067 kHttpResponsePartialContent);
1068}
1069
1070// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1071// fetcher will signal a (failed) completed transfer to the delegate.
1072TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1073 if (!this->test_.IsMulti())
1074 return;
1075
Ben Chan02f7c1d2014-10-18 15:18:02 -07001076 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001077 ASSERT_TRUE(server->started_);
1078
Ben Chanf9cb98c2014-09-21 18:31:30 -07001079 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001080 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(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001083 LocalServerUrlForPath(server->GetPort(),
1084 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001085 kBigLength)),
1086 ranges,
1087 "abcdefghijabcdefghijabcde", // only received the first chunk
1088 25,
1089 kHttpResponseUndefined);
1090}
1091
1092
1093
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001094namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001095class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001096 public:
1097 virtual void ReceivedBytes(HttpFetcher* fetcher,
1098 const char* bytes, int length) {
1099 ADD_FAILURE();
1100 }
1101 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
1102 EXPECT_FALSE(successful);
1103 g_main_loop_quit(loop_);
1104 }
Darin Petkov9ce452b2010-11-17 14:33:28 -08001105 virtual void TransferTerminated(HttpFetcher* fetcher) {
1106 ADD_FAILURE();
1107 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001108 GMainLoop* loop_;
1109};
1110
1111} // namespace
1112
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001113TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001114 if (this->test_.IsMock() || this->test_.IsMulti())
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001115 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001116
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001117 for (int i = 0; i < 2; i++) {
Ben Chan02f7c1d2014-10-18 15:18:02 -07001118 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001119 ASSERT_TRUE(server->started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001120
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001121 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001122 {
1123 BlockedTransferTestDelegate delegate;
1124 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001125
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001126 bool is_allowed = (i != 0);
Ben Chan02f7c1d2014-10-18 15:18:02 -07001127 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
Jay Srinivasan43488792012-06-19 00:25:31 -07001128
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001129 bool is_official_build = (i == 1);
1130 LOG(INFO) << "is_update_allowed_over_connection: " << is_allowed;
1131 LOG(INFO) << "is_official_build: " << is_official_build;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001132 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
1133 dynamic_cast<FakeSystemState*>(fetcher->GetSystemState())
Gilad Arnold1f847232014-04-07 12:07:49 -07001134 ->fake_hardware()->SetIsOfficialBuild(is_official_build);
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001135 fetcher->set_delegate(&delegate);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001136
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001137 StartTransferArgs start_xfer_args =
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001138 {fetcher.get(),
1139 LocalServerUrlForPath(server->GetPort(),
1140 this->test_.SmallUrl(server->GetPort()))};
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001141
Jay Srinivasan135a58b2012-07-13 12:46:49 -07001142 g_timeout_add(0, StartTransfer, &start_xfer_args);
1143 g_main_loop_run(loop);
1144 }
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001145 g_main_loop_unref(loop);
1146 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001147}
1148
rspangler@google.com49fdf182009-10-10 00:57:34 +00001149} // namespace chromeos_update_engine