blob: 87dda7831df45ea36131369d30e8813f803e5c41 [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <unistd.h>
Darin Petkov41c2fcf2010-08-25 13:14:48 -07006
adlr@google.comc98a7ed2009-12-04 18:54:03 +00007#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -07008#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +00009#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070010
Chris Masone790e62e2010-08-12 10:41:18 -070011#include "base/logging.h"
Darin Petkov41c2fcf2010-08-25 13:14:48 -070012#include "base/scoped_ptr.h"
13#include "base/string_util.h"
14#include "glib.h"
15#include "gtest/gtest.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000016#include "update_engine/libcurl_http_fetcher.h"
17#include "update_engine/mock_http_fetcher.h"
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070018#include "update_engine/multi_http_fetcher.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000019
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070020using std::make_pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000021using std::string;
22using std::vector;
23
rspangler@google.com49fdf182009-10-10 00:57:34 +000024namespace chromeos_update_engine {
25
26namespace {
Darin Petkovf67bb1f2010-11-08 16:10:26 -080027// WARNING, if you update these, you must also update test_http_server.cc.
28const char* const kServerPort = "8088";
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070029const int kBigSize = 100000;
rspangler@google.com49fdf182009-10-10 00:57:34 +000030string LocalServerUrlForPath(const string& path) {
31 return string("http://127.0.0.1:") + kServerPort + path;
32}
33}
34
35template <typename T>
36class HttpFetcherTest : public ::testing::Test {
37 public:
38 HttpFetcher* NewLargeFetcher() = 0;
39 HttpFetcher* NewSmallFetcher() = 0;
40 string BigUrl() const = 0;
41 string SmallUrl() const = 0;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000042 bool IsMock() const = 0;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070043 bool IsMulti() const = 0;
rspangler@google.com49fdf182009-10-10 00:57:34 +000044};
45
46class NullHttpServer {
47 public:
48 NullHttpServer() : started_(true) {}
49 ~NullHttpServer() {}
50 bool started_;
51};
52
53
54template <>
55class HttpFetcherTest<MockHttpFetcher> : public ::testing::Test {
56 public:
57 HttpFetcher* NewLargeFetcher() {
58 vector<char> big_data(1000000);
59 return new MockHttpFetcher(big_data.data(), big_data.size());
60 }
61 HttpFetcher* NewSmallFetcher() {
62 return new MockHttpFetcher("x", 1);
63 }
64 string BigUrl() const {
65 return "unused://unused";
66 }
67 string SmallUrl() const {
68 return "unused://unused";
69 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +000070 bool IsMock() const { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070071 bool IsMulti() const { return false; }
rspangler@google.com49fdf182009-10-10 00:57:34 +000072 typedef NullHttpServer HttpServer;
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070073 void IgnoreServerAborting(HttpServer* server) const {}
rspangler@google.com49fdf182009-10-10 00:57:34 +000074};
75
76class PythonHttpServer {
77 public:
78 PythonHttpServer() {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000079 char *argv[2] = {strdup("./test_http_server"), NULL};
rspangler@google.com49fdf182009-10-10 00:57:34 +000080 GError *err;
81 started_ = false;
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070082 validate_quit_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +000083 if (!g_spawn_async(NULL,
84 argv,
85 NULL,
86 G_SPAWN_DO_NOT_REAP_CHILD,
87 NULL,
88 NULL,
89 &pid_,
90 &err)) {
91 return;
92 }
93 int rc = 1;
Andrew de los Reyes3270f742010-07-15 22:28:14 -070094 int tries = 10;
95 started_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +000096 while (0 != rc) {
Andrew de los Reyes3270f742010-07-15 22:28:14 -070097 LOG(INFO) << "running wget to start";
rspangler@google.com49fdf182009-10-10 00:57:34 +000098 rc = system((string("wget --output-document=/dev/null ") +
99 LocalServerUrlForPath("/test")).c_str());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700100 LOG(INFO) << "done running wget to start";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000101 usleep(10 * 1000); // 10 ms
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700102 tries--;
103 if (tries == 0) {
104 LOG(ERROR) << "Unable to start server.";
105 started_ = false;
106 break;
107 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000108 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000109 free(argv[0]);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700110 LOG(INFO) << "gdb attach now!";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000111 return;
112 }
113 ~PythonHttpServer() {
114 if (!started_)
115 return;
116 // request that the server exit itself
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700117 LOG(INFO) << "running wget to exit";
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700118 int rc = system((string("wget -t 1 --output-document=/dev/null ") +
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700119 LocalServerUrlForPath("/quitquitquit")).c_str());
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700120 LOG(INFO) << "done running wget to exit";
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700121 if (validate_quit_)
122 EXPECT_EQ(0, rc);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000123 waitpid(pid_, NULL, 0);
124 }
125 GPid pid_;
126 bool started_;
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700127 bool validate_quit_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000128};
129
130template <>
131class HttpFetcherTest<LibcurlHttpFetcher> : public ::testing::Test {
132 public:
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700133 virtual HttpFetcher* NewLargeFetcher() {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000134 LibcurlHttpFetcher *ret = new LibcurlHttpFetcher;
Darin Petkovb83371f2010-08-17 09:34:49 -0700135 // Speed up test execution.
136 ret->set_idle_seconds(1);
137 ret->set_retry_seconds(1);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700138 ret->SetConnectionAsExpensive(false);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700139 ret->SetBuildType(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000140 return ret;
141 }
142 HttpFetcher* NewSmallFetcher() {
143 return NewLargeFetcher();
144 }
145 string BigUrl() const {
146 return LocalServerUrlForPath("/big");
147 }
148 string SmallUrl() const {
149 return LocalServerUrlForPath("/foo");
150 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000151 bool IsMock() const { return false; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700152 bool IsMulti() const { return false; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000153 typedef PythonHttpServer HttpServer;
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700154 void IgnoreServerAborting(HttpServer* server) const {
155 PythonHttpServer *pyserver = reinterpret_cast<PythonHttpServer*>(server);
156 pyserver->validate_quit_ = false;
157 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000158};
159
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700160template <>
161class HttpFetcherTest<MultiHttpFetcher<LibcurlHttpFetcher> >
162 : public HttpFetcherTest<LibcurlHttpFetcher> {
163 public:
164 HttpFetcher* NewLargeFetcher() {
165 MultiHttpFetcher<LibcurlHttpFetcher> *ret =
166 new MultiHttpFetcher<LibcurlHttpFetcher>;
167 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect
168 ranges(1, make_pair(0, -1));
169 ret->set_ranges(ranges);
170 // Speed up test execution.
171 ret->set_idle_seconds(1);
172 ret->set_retry_seconds(1);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700173 ret->SetConnectionAsExpensive(false);
174 ret->SetBuildType(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700175 return ret;
176 }
177 bool IsMulti() const { return true; }
178};
179
180typedef ::testing::Types<LibcurlHttpFetcher,
181 MockHttpFetcher,
182 MultiHttpFetcher<LibcurlHttpFetcher> >
183HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000184TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
185
186namespace {
187class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000188 public:
rspangler@google.com49fdf182009-10-10 00:57:34 +0000189 virtual void ReceivedBytes(HttpFetcher* fetcher,
190 const char* bytes, int length) {
191 char str[length + 1];
192 memset(str, 0, length + 1);
193 memcpy(str, bytes, length);
194 }
195 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkovcb466212010-08-26 09:40:11 -0700196 EXPECT_EQ(200, fetcher->http_response_code());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000197 g_main_loop_quit(loop_);
198 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800199 virtual void TransferTerminated(HttpFetcher* fetcher) {
200 ADD_FAILURE();
201 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000202 GMainLoop* loop_;
203};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000204
205struct StartTransferArgs {
206 HttpFetcher *http_fetcher;
207 string url;
208};
209
210gboolean StartTransfer(gpointer data) {
211 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
212 args->http_fetcher->BeginTransfer(args->url);
213 return FALSE;
214}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000215} // namespace {}
216
217TYPED_TEST(HttpFetcherTest, SimpleTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700218 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000219 {
220 HttpFetcherTestDelegate delegate;
221 delegate.loop_ = loop;
222 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
223 fetcher->set_delegate(&delegate);
224
225 typename TestFixture::HttpServer server;
226 ASSERT_TRUE(server.started_);
227
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000228 StartTransferArgs start_xfer_args = {fetcher.get(), this->SmallUrl()};
229
230 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000231 g_main_loop_run(loop);
232 }
233 g_main_loop_unref(loop);
234}
235
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700236TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700237 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700238 {
239 HttpFetcherTestDelegate delegate;
240 delegate.loop_ = loop;
241 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
242 fetcher->set_delegate(&delegate);
243
244 typename TestFixture::HttpServer server;
245 ASSERT_TRUE(server.started_);
246
247 StartTransferArgs start_xfer_args = {fetcher.get(), this->BigUrl()};
248
249 g_timeout_add(0, StartTransfer, &start_xfer_args);
250 g_main_loop_run(loop);
251 }
252 g_main_loop_unref(loop);
253}
254
rspangler@google.com49fdf182009-10-10 00:57:34 +0000255namespace {
256class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
257 public:
258 virtual void ReceivedBytes(HttpFetcher* fetcher,
259 const char* bytes, int length) {
260 char str[length + 1];
rspangler@google.com49fdf182009-10-10 00:57:34 +0000261 memset(str, 0, length + 1);
262 memcpy(str, bytes, length);
263 CHECK(!paused_);
264 paused_ = true;
265 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000266 }
267 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
268 g_main_loop_quit(loop_);
269 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800270 virtual void TransferTerminated(HttpFetcher* fetcher) {
271 ADD_FAILURE();
272 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000273 void Unpause() {
274 CHECK(paused_);
275 paused_ = false;
276 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000277 }
278 bool paused_;
279 HttpFetcher* fetcher_;
280 GMainLoop* loop_;
281};
282
283gboolean UnpausingTimeoutCallback(gpointer data) {
284 PausingHttpFetcherTestDelegate *delegate =
285 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
286 if (delegate->paused_)
287 delegate->Unpause();
288 return TRUE;
289}
290} // namespace {}
291
292TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700293 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000294 {
295 PausingHttpFetcherTestDelegate delegate;
296 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
297 delegate.paused_ = false;
298 delegate.loop_ = loop;
299 delegate.fetcher_ = fetcher.get();
300 fetcher->set_delegate(&delegate);
301
302 typename TestFixture::HttpServer server;
303 ASSERT_TRUE(server.started_);
304 GSource* timeout_source_;
305 timeout_source_ = g_timeout_source_new(0); // ms
306 g_source_set_callback(timeout_source_, UnpausingTimeoutCallback, &delegate,
307 NULL);
308 g_source_attach(timeout_source_, NULL);
309 fetcher->BeginTransfer(this->BigUrl());
310
311 g_main_loop_run(loop);
312 g_source_destroy(timeout_source_);
313 }
314 g_main_loop_unref(loop);
315}
316
317namespace {
318class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
319 public:
320 virtual void ReceivedBytes(HttpFetcher* fetcher,
321 const char* bytes, int length) {}
322 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800323 ADD_FAILURE(); // We should never get here
rspangler@google.com49fdf182009-10-10 00:57:34 +0000324 g_main_loop_quit(loop_);
325 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800326 virtual void TransferTerminated(HttpFetcher* fetcher) {
327 EXPECT_EQ(fetcher, fetcher_.get());
328 EXPECT_FALSE(once_);
329 EXPECT_TRUE(callback_once_);
330 callback_once_ = false;
331 // |fetcher| can be destroyed during this callback.
332 fetcher_.reset(NULL);
333 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000334 void TerminateTransfer() {
335 CHECK(once_);
336 once_ = false;
337 fetcher_->TerminateTransfer();
338 }
339 void EndLoop() {
340 g_main_loop_quit(loop_);
341 }
342 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800343 bool callback_once_;
344 scoped_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000345 GMainLoop* loop_;
346};
347
348gboolean AbortingTimeoutCallback(gpointer data) {
349 AbortingHttpFetcherTestDelegate *delegate =
350 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
351 if (delegate->once_) {
352 delegate->TerminateTransfer();
353 return TRUE;
354 } else {
355 delegate->EndLoop();
356 return FALSE;
357 }
358}
359} // namespace {}
360
361TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700362 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000363 {
364 AbortingHttpFetcherTestDelegate delegate;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800365 delegate.fetcher_.reset(this->NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000366 delegate.once_ = true;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800367 delegate.callback_once_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000368 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800369 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000370
371 typename TestFixture::HttpServer server;
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700372 this->IgnoreServerAborting(&server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000373 ASSERT_TRUE(server.started_);
374 GSource* timeout_source_;
375 timeout_source_ = g_timeout_source_new(0); // ms
376 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
377 NULL);
378 g_source_attach(timeout_source_, NULL);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800379 delegate.fetcher_->BeginTransfer(this->BigUrl());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000380
381 g_main_loop_run(loop);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800382 CHECK(!delegate.once_);
383 CHECK(!delegate.callback_once_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000384 g_source_destroy(timeout_source_);
385 }
386 g_main_loop_unref(loop);
387}
388
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000389namespace {
390class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
391 public:
392 virtual void ReceivedBytes(HttpFetcher* fetcher,
393 const char* bytes, int length) {
394 data.append(bytes, length);
395 }
396 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700397 EXPECT_TRUE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700398 EXPECT_EQ(206, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000399 g_main_loop_quit(loop_);
400 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800401 virtual void TransferTerminated(HttpFetcher* fetcher) {
402 ADD_FAILURE();
403 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000404 string data;
405 GMainLoop* loop_;
406};
407} // namespace {}
408
409TYPED_TEST(HttpFetcherTest, FlakyTest) {
410 if (this->IsMock())
411 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700412 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000413 {
414 FlakyHttpFetcherTestDelegate delegate;
415 delegate.loop_ = loop;
416 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
417 fetcher->set_delegate(&delegate);
418
419 typename TestFixture::HttpServer server;
420 ASSERT_TRUE(server.started_);
421
422 StartTransferArgs start_xfer_args = {
423 fetcher.get(),
424 LocalServerUrlForPath("/flaky")
425 };
426
427 g_timeout_add(0, StartTransfer, &start_xfer_args);
428 g_main_loop_run(loop);
429
430 // verify the data we get back
431 ASSERT_EQ(100000, delegate.data.size());
432 for (int i = 0; i < 100000; i += 10) {
433 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
434 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
435 }
436 }
437 g_main_loop_unref(loop);
438}
439
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700440namespace {
441class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
442 public:
443 FailureHttpFetcherTestDelegate() : loop_(NULL), server_(NULL) {}
444 virtual void ReceivedBytes(HttpFetcher* fetcher,
445 const char* bytes, int length) {
446 if (server_) {
447 LOG(INFO) << "Stopping server";
448 delete server_;
449 LOG(INFO) << "server stopped";
450 server_ = NULL;
451 }
452 }
453 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
454 EXPECT_FALSE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700455 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700456 g_main_loop_quit(loop_);
457 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800458 virtual void TransferTerminated(HttpFetcher* fetcher) {
459 ADD_FAILURE();
460 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700461 GMainLoop* loop_;
462 PythonHttpServer* server_;
463};
464} // namespace {}
465
466
467TYPED_TEST(HttpFetcherTest, FailureTest) {
468 if (this->IsMock())
469 return;
470 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
471 {
472 FailureHttpFetcherTestDelegate delegate;
473 delegate.loop_ = loop;
474 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
475 fetcher->set_delegate(&delegate);
476
477 StartTransferArgs start_xfer_args = {
478 fetcher.get(),
479 LocalServerUrlForPath(this->SmallUrl())
480 };
481
482 g_timeout_add(0, StartTransfer, &start_xfer_args);
483 g_main_loop_run(loop);
484
485 // Exiting and testing happens in the delegate
486 }
487 g_main_loop_unref(loop);
488}
489
490TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
491 if (this->IsMock())
492 return;
493 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
494 {
495 FailureHttpFetcherTestDelegate delegate;
496 delegate.loop_ = loop;
497 delegate.server_ = new PythonHttpServer;
498 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
499 fetcher->set_delegate(&delegate);
500
501 StartTransferArgs start_xfer_args = {
502 fetcher.get(),
503 LocalServerUrlForPath("/flaky")
504 };
505
506 g_timeout_add(0, StartTransfer, &start_xfer_args);
507 g_main_loop_run(loop);
508
509 // Exiting and testing happens in the delegate
510 }
511 g_main_loop_unref(loop);
512}
513
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700514namespace {
515const int kRedirectCodes[] = { 301, 302, 303, 307 };
516
517class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
518 public:
519 RedirectHttpFetcherTestDelegate(bool expected_successful)
520 : expected_successful_(expected_successful) {}
521 virtual void ReceivedBytes(HttpFetcher* fetcher,
522 const char* bytes, int length) {
523 data.append(bytes, length);
524 }
525 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
526 EXPECT_EQ(expected_successful_, successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700527 if (expected_successful_)
528 EXPECT_EQ(200, fetcher->http_response_code());
529 else {
530 EXPECT_GE(fetcher->http_response_code(), 301);
531 EXPECT_LE(fetcher->http_response_code(), 307);
532 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700533 g_main_loop_quit(loop_);
534 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800535 virtual void TransferTerminated(HttpFetcher* fetcher) {
536 ADD_FAILURE();
537 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700538 bool expected_successful_;
539 string data;
540 GMainLoop* loop_;
541};
542
543// RedirectTest takes ownership of |http_fetcher|.
544void RedirectTest(bool expected_successful,
545 const string& url,
546 HttpFetcher* http_fetcher) {
547 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
548 RedirectHttpFetcherTestDelegate delegate(expected_successful);
549 delegate.loop_ = loop;
550 scoped_ptr<HttpFetcher> fetcher(http_fetcher);
551 fetcher->set_delegate(&delegate);
552
553 StartTransferArgs start_xfer_args =
554 { fetcher.get(), LocalServerUrlForPath(url) };
555
556 g_timeout_add(0, StartTransfer, &start_xfer_args);
557 g_main_loop_run(loop);
558 if (expected_successful) {
559 // verify the data we get back
560 ASSERT_EQ(1000, delegate.data.size());
561 for (int i = 0; i < 1000; i += 10) {
562 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
563 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
564 }
565 }
566 g_main_loop_unref(loop);
567}
568} // namespace {}
569
570TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
571 if (this->IsMock())
572 return;
573 typename TestFixture::HttpServer server;
574 ASSERT_TRUE(server.started_);
575 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
576 const string url = base::StringPrintf("/redirect/%d/medium",
577 kRedirectCodes[c]);
578 RedirectTest(true, url, this->NewLargeFetcher());
579 }
580}
581
582TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
583 if (this->IsMock())
584 return;
585 typename TestFixture::HttpServer server;
586 ASSERT_TRUE(server.started_);
587 string url;
588 for (int r = 0; r < LibcurlHttpFetcher::kMaxRedirects; r++) {
589 url += base::StringPrintf("/redirect/%d",
590 kRedirectCodes[r % arraysize(kRedirectCodes)]);
591 }
592 url += "/medium";
593 RedirectTest(true, url, this->NewLargeFetcher());
594}
595
596TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
597 if (this->IsMock())
598 return;
599 typename TestFixture::HttpServer server;
600 ASSERT_TRUE(server.started_);
601 string url;
602 for (int r = 0; r < LibcurlHttpFetcher::kMaxRedirects + 1; r++) {
603 url += base::StringPrintf("/redirect/%d",
604 kRedirectCodes[r % arraysize(kRedirectCodes)]);
605 }
606 url += "/medium";
607 RedirectTest(false, url, this->NewLargeFetcher());
608}
609
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700610namespace {
611class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
612 public:
613 MultiHttpFetcherTestDelegate(int expected_response_code)
614 : expected_response_code_(expected_response_code) {}
615 virtual void ReceivedBytes(HttpFetcher* fetcher,
616 const char* bytes, int length) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800617 EXPECT_EQ(fetcher, fetcher_.get());
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700618 data.append(bytes, length);
619 }
620 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800621 EXPECT_EQ(fetcher, fetcher_.get());
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700622 EXPECT_EQ(expected_response_code_ != 0, successful);
623 if (expected_response_code_ != 0)
624 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800625 // Destroy the fetcher (because we're allowed to).
626 fetcher_.reset(NULL);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700627 g_main_loop_quit(loop_);
628 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800629 virtual void TransferTerminated(HttpFetcher* fetcher) {
630 ADD_FAILURE();
631 }
632 scoped_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700633 int expected_response_code_;
634 string data;
635 GMainLoop* loop_;
636};
637
638void MultiTest(HttpFetcher* fetcher_in,
639 const string& url,
640 const MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect& ranges,
641 const string& expected_prefix,
642 off_t expected_size,
643 int expected_response_code) {
644 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
645 {
646 MultiHttpFetcherTestDelegate delegate(expected_response_code);
647 delegate.loop_ = loop;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800648 delegate.fetcher_.reset(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700649 MultiHttpFetcher<LibcurlHttpFetcher>* multi_fetcher =
Darin Petkov9ce452b2010-11-17 14:33:28 -0800650 dynamic_cast<MultiHttpFetcher<LibcurlHttpFetcher>*>(fetcher_in);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700651 ASSERT_TRUE(multi_fetcher);
652 multi_fetcher->set_ranges(ranges);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700653 multi_fetcher->SetConnectionAsExpensive(false);
654 multi_fetcher->SetBuildType(false);
Darin Petkov9ce452b2010-11-17 14:33:28 -0800655 multi_fetcher->set_delegate(&delegate);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700656
Darin Petkov9ce452b2010-11-17 14:33:28 -0800657 StartTransferArgs start_xfer_args = {multi_fetcher, url};
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700658
659 g_timeout_add(0, StartTransfer, &start_xfer_args);
660 g_main_loop_run(loop);
661
662 EXPECT_EQ(expected_size, delegate.data.size());
663 EXPECT_EQ(expected_prefix,
664 string(delegate.data.data(), expected_prefix.size()));
665 }
666 g_main_loop_unref(loop);
667}
668} // namespace {}
669
Darin Petkov9ce452b2010-11-17 14:33:28 -0800670TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700671 if (!this->IsMulti())
672 return;
673 typename TestFixture::HttpServer server;
674 ASSERT_TRUE(server.started_);
675
676 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
677 ranges.push_back(make_pair(0, 25));
678 ranges.push_back(make_pair(99, -1));
679 MultiTest(this->NewLargeFetcher(),
680 this->BigUrl(),
681 ranges,
682 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
683 kBigSize - (99 - 25),
684 206);
685}
686
687TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
688 if (!this->IsMulti())
689 return;
690 typename TestFixture::HttpServer server;
691 ASSERT_TRUE(server.started_);
692
693 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
694 ranges.push_back(make_pair(0, 24));
695 MultiTest(this->NewLargeFetcher(),
696 this->BigUrl(),
697 ranges,
698 "abcdefghijabcdefghijabcd",
699 24,
700 200);
701}
702
703TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
704 if (!this->IsMulti())
705 return;
706 typename TestFixture::HttpServer server;
707 ASSERT_TRUE(server.started_);
708
709 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
710 ranges.push_back(make_pair(kBigSize - 2, -1));
711 ranges.push_back(make_pair(kBigSize - 3, -1));
712 MultiTest(this->NewLargeFetcher(),
713 this->BigUrl(),
714 ranges,
715 "ijhij",
716 5,
717 206);
718}
719
720TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
721 if (!this->IsMulti())
722 return;
723 typename TestFixture::HttpServer server;
724 ASSERT_TRUE(server.started_);
725
726 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
727 ranges.push_back(make_pair(kBigSize - 2, 4));
728 for (int i = 0; i < 2; ++i) {
729 MultiTest(this->NewLargeFetcher(),
730 this->BigUrl(),
731 ranges,
732 "ij",
733 2,
734 0);
735 ranges.push_back(make_pair(0, 5));
736 }
737}
738
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700739namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700740class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700741 public:
742 virtual void ReceivedBytes(HttpFetcher* fetcher,
743 const char* bytes, int length) {
744 ADD_FAILURE();
745 }
746 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
747 EXPECT_FALSE(successful);
748 g_main_loop_quit(loop_);
749 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800750 virtual void TransferTerminated(HttpFetcher* fetcher) {
751 ADD_FAILURE();
752 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700753 GMainLoop* loop_;
754};
755
756} // namespace
757
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700758TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700759 if (this->IsMock() || this->IsMulti())
760 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700761
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700762 for (int i = 0; i < 2; i++) {
763 typename TestFixture::HttpServer server;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700764
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700765 ASSERT_TRUE(server.started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700766
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700767 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
768 BlockedTransferTestDelegate delegate;
769 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700770
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700771 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
772 LibcurlHttpFetcher* curl_fetcher =
773 dynamic_cast<LibcurlHttpFetcher*>(fetcher.get());
774 bool is_expensive_connection = (i == 0);
775 bool is_official_build = (i == 1);
776 LOG(INFO) << "is_expensive_connection: " << is_expensive_connection;
777 LOG(INFO) << "is_official_build: " << is_official_build;
778 curl_fetcher->SetConnectionAsExpensive(is_expensive_connection);
779 curl_fetcher->SetBuildType(is_official_build);
780 fetcher->set_delegate(&delegate);
781
782 StartTransferArgs start_xfer_args =
783 { fetcher.get(), LocalServerUrlForPath(this->SmallUrl()) };
784
785 g_timeout_add(0, StartTransfer, &start_xfer_args);
786 g_main_loop_run(loop);
787 g_main_loop_unref(loop);
788 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700789}
790
rspangler@google.com49fdf182009-10-10 00:57:34 +0000791} // namespace chromeos_update_engine