blob: 6c420a0b513266def80515303ebb39f9deecde5d [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 {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070027// WARNING, if you update these, you must also update test_http_server.py
rspangler@google.com49fdf182009-10-10 00:57:34 +000028const char* const kServerPort = "8080";
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 }
199 GMainLoop* loop_;
200};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000201
202struct StartTransferArgs {
203 HttpFetcher *http_fetcher;
204 string url;
205};
206
207gboolean StartTransfer(gpointer data) {
208 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
209 args->http_fetcher->BeginTransfer(args->url);
210 return FALSE;
211}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000212} // namespace {}
213
214TYPED_TEST(HttpFetcherTest, SimpleTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700215 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000216 {
217 HttpFetcherTestDelegate delegate;
218 delegate.loop_ = loop;
219 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
220 fetcher->set_delegate(&delegate);
221
222 typename TestFixture::HttpServer server;
223 ASSERT_TRUE(server.started_);
224
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000225 StartTransferArgs start_xfer_args = {fetcher.get(), this->SmallUrl()};
226
227 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000228 g_main_loop_run(loop);
229 }
230 g_main_loop_unref(loop);
231}
232
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700233TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700234 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700235 {
236 HttpFetcherTestDelegate delegate;
237 delegate.loop_ = loop;
238 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
239 fetcher->set_delegate(&delegate);
240
241 typename TestFixture::HttpServer server;
242 ASSERT_TRUE(server.started_);
243
244 StartTransferArgs start_xfer_args = {fetcher.get(), this->BigUrl()};
245
246 g_timeout_add(0, StartTransfer, &start_xfer_args);
247 g_main_loop_run(loop);
248 }
249 g_main_loop_unref(loop);
250}
251
rspangler@google.com49fdf182009-10-10 00:57:34 +0000252namespace {
253class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
254 public:
255 virtual void ReceivedBytes(HttpFetcher* fetcher,
256 const char* bytes, int length) {
257 char str[length + 1];
rspangler@google.com49fdf182009-10-10 00:57:34 +0000258 memset(str, 0, length + 1);
259 memcpy(str, bytes, length);
260 CHECK(!paused_);
261 paused_ = true;
262 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000263 }
264 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
265 g_main_loop_quit(loop_);
266 }
267 void Unpause() {
268 CHECK(paused_);
269 paused_ = false;
270 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000271 }
272 bool paused_;
273 HttpFetcher* fetcher_;
274 GMainLoop* loop_;
275};
276
277gboolean UnpausingTimeoutCallback(gpointer data) {
278 PausingHttpFetcherTestDelegate *delegate =
279 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
280 if (delegate->paused_)
281 delegate->Unpause();
282 return TRUE;
283}
284} // namespace {}
285
286TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700287 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000288 {
289 PausingHttpFetcherTestDelegate delegate;
290 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
291 delegate.paused_ = false;
292 delegate.loop_ = loop;
293 delegate.fetcher_ = fetcher.get();
294 fetcher->set_delegate(&delegate);
295
296 typename TestFixture::HttpServer server;
297 ASSERT_TRUE(server.started_);
298 GSource* timeout_source_;
299 timeout_source_ = g_timeout_source_new(0); // ms
300 g_source_set_callback(timeout_source_, UnpausingTimeoutCallback, &delegate,
301 NULL);
302 g_source_attach(timeout_source_, NULL);
303 fetcher->BeginTransfer(this->BigUrl());
304
305 g_main_loop_run(loop);
306 g_source_destroy(timeout_source_);
307 }
308 g_main_loop_unref(loop);
309}
310
311namespace {
312class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
313 public:
314 virtual void ReceivedBytes(HttpFetcher* fetcher,
315 const char* bytes, int length) {}
316 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
317 CHECK(false); // We should never get here
318 g_main_loop_quit(loop_);
319 }
320 void TerminateTransfer() {
321 CHECK(once_);
322 once_ = false;
323 fetcher_->TerminateTransfer();
324 }
325 void EndLoop() {
326 g_main_loop_quit(loop_);
327 }
328 bool once_;
329 HttpFetcher* fetcher_;
330 GMainLoop* loop_;
331};
332
333gboolean AbortingTimeoutCallback(gpointer data) {
334 AbortingHttpFetcherTestDelegate *delegate =
335 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
336 if (delegate->once_) {
337 delegate->TerminateTransfer();
338 return TRUE;
339 } else {
340 delegate->EndLoop();
341 return FALSE;
342 }
343}
344} // namespace {}
345
346TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700347 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000348 {
349 AbortingHttpFetcherTestDelegate delegate;
350 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
351 delegate.once_ = true;
352 delegate.loop_ = loop;
353 delegate.fetcher_ = fetcher.get();
354 fetcher->set_delegate(&delegate);
355
356 typename TestFixture::HttpServer server;
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700357 this->IgnoreServerAborting(&server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000358 ASSERT_TRUE(server.started_);
359 GSource* timeout_source_;
360 timeout_source_ = g_timeout_source_new(0); // ms
361 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
362 NULL);
363 g_source_attach(timeout_source_, NULL);
364 fetcher->BeginTransfer(this->BigUrl());
365
366 g_main_loop_run(loop);
367 g_source_destroy(timeout_source_);
368 }
369 g_main_loop_unref(loop);
370}
371
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000372namespace {
373class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
374 public:
375 virtual void ReceivedBytes(HttpFetcher* fetcher,
376 const char* bytes, int length) {
377 data.append(bytes, length);
378 }
379 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700380 EXPECT_TRUE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700381 EXPECT_EQ(206, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000382 g_main_loop_quit(loop_);
383 }
384 string data;
385 GMainLoop* loop_;
386};
387} // namespace {}
388
389TYPED_TEST(HttpFetcherTest, FlakyTest) {
390 if (this->IsMock())
391 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700392 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000393 {
394 FlakyHttpFetcherTestDelegate delegate;
395 delegate.loop_ = loop;
396 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
397 fetcher->set_delegate(&delegate);
398
399 typename TestFixture::HttpServer server;
400 ASSERT_TRUE(server.started_);
401
402 StartTransferArgs start_xfer_args = {
403 fetcher.get(),
404 LocalServerUrlForPath("/flaky")
405 };
406
407 g_timeout_add(0, StartTransfer, &start_xfer_args);
408 g_main_loop_run(loop);
409
410 // verify the data we get back
411 ASSERT_EQ(100000, delegate.data.size());
412 for (int i = 0; i < 100000; i += 10) {
413 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
414 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
415 }
416 }
417 g_main_loop_unref(loop);
418}
419
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700420namespace {
421class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
422 public:
423 FailureHttpFetcherTestDelegate() : loop_(NULL), server_(NULL) {}
424 virtual void ReceivedBytes(HttpFetcher* fetcher,
425 const char* bytes, int length) {
426 if (server_) {
427 LOG(INFO) << "Stopping server";
428 delete server_;
429 LOG(INFO) << "server stopped";
430 server_ = NULL;
431 }
432 }
433 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
434 EXPECT_FALSE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700435 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700436 g_main_loop_quit(loop_);
437 }
438 GMainLoop* loop_;
439 PythonHttpServer* server_;
440};
441} // namespace {}
442
443
444TYPED_TEST(HttpFetcherTest, FailureTest) {
445 if (this->IsMock())
446 return;
447 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
448 {
449 FailureHttpFetcherTestDelegate delegate;
450 delegate.loop_ = loop;
451 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
452 fetcher->set_delegate(&delegate);
453
454 StartTransferArgs start_xfer_args = {
455 fetcher.get(),
456 LocalServerUrlForPath(this->SmallUrl())
457 };
458
459 g_timeout_add(0, StartTransfer, &start_xfer_args);
460 g_main_loop_run(loop);
461
462 // Exiting and testing happens in the delegate
463 }
464 g_main_loop_unref(loop);
465}
466
467TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
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 delegate.server_ = new PythonHttpServer;
475 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
476 fetcher->set_delegate(&delegate);
477
478 StartTransferArgs start_xfer_args = {
479 fetcher.get(),
480 LocalServerUrlForPath("/flaky")
481 };
482
483 g_timeout_add(0, StartTransfer, &start_xfer_args);
484 g_main_loop_run(loop);
485
486 // Exiting and testing happens in the delegate
487 }
488 g_main_loop_unref(loop);
489}
490
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700491namespace {
492const int kRedirectCodes[] = { 301, 302, 303, 307 };
493
494class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
495 public:
496 RedirectHttpFetcherTestDelegate(bool expected_successful)
497 : expected_successful_(expected_successful) {}
498 virtual void ReceivedBytes(HttpFetcher* fetcher,
499 const char* bytes, int length) {
500 data.append(bytes, length);
501 }
502 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
503 EXPECT_EQ(expected_successful_, successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700504 if (expected_successful_)
505 EXPECT_EQ(200, fetcher->http_response_code());
506 else {
507 EXPECT_GE(fetcher->http_response_code(), 301);
508 EXPECT_LE(fetcher->http_response_code(), 307);
509 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700510 g_main_loop_quit(loop_);
511 }
512 bool expected_successful_;
513 string data;
514 GMainLoop* loop_;
515};
516
517// RedirectTest takes ownership of |http_fetcher|.
518void RedirectTest(bool expected_successful,
519 const string& url,
520 HttpFetcher* http_fetcher) {
521 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
522 RedirectHttpFetcherTestDelegate delegate(expected_successful);
523 delegate.loop_ = loop;
524 scoped_ptr<HttpFetcher> fetcher(http_fetcher);
525 fetcher->set_delegate(&delegate);
526
527 StartTransferArgs start_xfer_args =
528 { fetcher.get(), LocalServerUrlForPath(url) };
529
530 g_timeout_add(0, StartTransfer, &start_xfer_args);
531 g_main_loop_run(loop);
532 if (expected_successful) {
533 // verify the data we get back
534 ASSERT_EQ(1000, delegate.data.size());
535 for (int i = 0; i < 1000; i += 10) {
536 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
537 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
538 }
539 }
540 g_main_loop_unref(loop);
541}
542} // namespace {}
543
544TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
545 if (this->IsMock())
546 return;
547 typename TestFixture::HttpServer server;
548 ASSERT_TRUE(server.started_);
549 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
550 const string url = base::StringPrintf("/redirect/%d/medium",
551 kRedirectCodes[c]);
552 RedirectTest(true, url, this->NewLargeFetcher());
553 }
554}
555
556TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
557 if (this->IsMock())
558 return;
559 typename TestFixture::HttpServer server;
560 ASSERT_TRUE(server.started_);
561 string url;
562 for (int r = 0; r < LibcurlHttpFetcher::kMaxRedirects; r++) {
563 url += base::StringPrintf("/redirect/%d",
564 kRedirectCodes[r % arraysize(kRedirectCodes)]);
565 }
566 url += "/medium";
567 RedirectTest(true, url, this->NewLargeFetcher());
568}
569
570TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
571 if (this->IsMock())
572 return;
573 typename TestFixture::HttpServer server;
574 ASSERT_TRUE(server.started_);
575 string url;
576 for (int r = 0; r < LibcurlHttpFetcher::kMaxRedirects + 1; r++) {
577 url += base::StringPrintf("/redirect/%d",
578 kRedirectCodes[r % arraysize(kRedirectCodes)]);
579 }
580 url += "/medium";
581 RedirectTest(false, url, this->NewLargeFetcher());
582}
583
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700584namespace {
585class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
586 public:
587 MultiHttpFetcherTestDelegate(int expected_response_code)
588 : expected_response_code_(expected_response_code) {}
589 virtual void ReceivedBytes(HttpFetcher* fetcher,
590 const char* bytes, int length) {
591 data.append(bytes, length);
592 }
593 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
594 EXPECT_EQ(expected_response_code_ != 0, successful);
595 if (expected_response_code_ != 0)
596 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
597 g_main_loop_quit(loop_);
598 }
599 int expected_response_code_;
600 string data;
601 GMainLoop* loop_;
602};
603
604void MultiTest(HttpFetcher* fetcher_in,
605 const string& url,
606 const MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect& ranges,
607 const string& expected_prefix,
608 off_t expected_size,
609 int expected_response_code) {
610 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
611 {
612 MultiHttpFetcherTestDelegate delegate(expected_response_code);
613 delegate.loop_ = loop;
614 scoped_ptr<HttpFetcher> fetcher(fetcher_in);
615 MultiHttpFetcher<LibcurlHttpFetcher>* multi_fetcher =
616 dynamic_cast<MultiHttpFetcher<LibcurlHttpFetcher>*>(fetcher.get());
617 ASSERT_TRUE(multi_fetcher);
618 multi_fetcher->set_ranges(ranges);
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700619 multi_fetcher->SetConnectionAsExpensive(false);
620 multi_fetcher->SetBuildType(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700621 fetcher->set_delegate(&delegate);
622
623 StartTransferArgs start_xfer_args = {fetcher.get(), url};
624
625 g_timeout_add(0, StartTransfer, &start_xfer_args);
626 g_main_loop_run(loop);
627
628 EXPECT_EQ(expected_size, delegate.data.size());
629 EXPECT_EQ(expected_prefix,
630 string(delegate.data.data(), expected_prefix.size()));
631 }
632 g_main_loop_unref(loop);
633}
634} // namespace {}
635
636TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimplTest) {
637 if (!this->IsMulti())
638 return;
639 typename TestFixture::HttpServer server;
640 ASSERT_TRUE(server.started_);
641
642 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
643 ranges.push_back(make_pair(0, 25));
644 ranges.push_back(make_pair(99, -1));
645 MultiTest(this->NewLargeFetcher(),
646 this->BigUrl(),
647 ranges,
648 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
649 kBigSize - (99 - 25),
650 206);
651}
652
653TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
654 if (!this->IsMulti())
655 return;
656 typename TestFixture::HttpServer server;
657 ASSERT_TRUE(server.started_);
658
659 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
660 ranges.push_back(make_pair(0, 24));
661 MultiTest(this->NewLargeFetcher(),
662 this->BigUrl(),
663 ranges,
664 "abcdefghijabcdefghijabcd",
665 24,
666 200);
667}
668
669TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
670 if (!this->IsMulti())
671 return;
672 typename TestFixture::HttpServer server;
673 ASSERT_TRUE(server.started_);
674
675 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
676 ranges.push_back(make_pair(kBigSize - 2, -1));
677 ranges.push_back(make_pair(kBigSize - 3, -1));
678 MultiTest(this->NewLargeFetcher(),
679 this->BigUrl(),
680 ranges,
681 "ijhij",
682 5,
683 206);
684}
685
686TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
687 if (!this->IsMulti())
688 return;
689 typename TestFixture::HttpServer server;
690 ASSERT_TRUE(server.started_);
691
692 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
693 ranges.push_back(make_pair(kBigSize - 2, 4));
694 for (int i = 0; i < 2; ++i) {
695 MultiTest(this->NewLargeFetcher(),
696 this->BigUrl(),
697 ranges,
698 "ij",
699 2,
700 0);
701 ranges.push_back(make_pair(0, 5));
702 }
703}
704
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700705namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700706class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700707 public:
708 virtual void ReceivedBytes(HttpFetcher* fetcher,
709 const char* bytes, int length) {
710 ADD_FAILURE();
711 }
712 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
713 EXPECT_FALSE(successful);
714 g_main_loop_quit(loop_);
715 }
716 GMainLoop* loop_;
717};
718
719} // namespace
720
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700721TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700722 if (this->IsMock() || this->IsMulti())
723 return;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700724
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700725 for (int i = 0; i < 2; i++) {
726 typename TestFixture::HttpServer server;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700727
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700728 ASSERT_TRUE(server.started_);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700729
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700730 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
731 BlockedTransferTestDelegate delegate;
732 delegate.loop_ = loop;
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700733
Darin Petkovfc7a0ce2010-10-25 10:38:37 -0700734 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
735 LibcurlHttpFetcher* curl_fetcher =
736 dynamic_cast<LibcurlHttpFetcher*>(fetcher.get());
737 bool is_expensive_connection = (i == 0);
738 bool is_official_build = (i == 1);
739 LOG(INFO) << "is_expensive_connection: " << is_expensive_connection;
740 LOG(INFO) << "is_official_build: " << is_official_build;
741 curl_fetcher->SetConnectionAsExpensive(is_expensive_connection);
742 curl_fetcher->SetBuildType(is_official_build);
743 fetcher->set_delegate(&delegate);
744
745 StartTransferArgs start_xfer_args =
746 { fetcher.get(), LocalServerUrlForPath(this->SmallUrl()) };
747
748 g_timeout_add(0, StartTransfer, &start_xfer_args);
749 g_main_loop_run(loop);
750 g_main_loop_unref(loop);
751 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700752}
753
rspangler@google.com49fdf182009-10-10 00:57:34 +0000754} // namespace chromeos_update_engine