blob: bd167685c6bfa7d473460b273528961b36465fac [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);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000139 return ret;
140 }
141 HttpFetcher* NewSmallFetcher() {
142 return NewLargeFetcher();
143 }
144 string BigUrl() const {
145 return LocalServerUrlForPath("/big");
146 }
147 string SmallUrl() const {
148 return LocalServerUrlForPath("/foo");
149 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000150 bool IsMock() const { return false; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700151 bool IsMulti() const { return false; }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000152 typedef PythonHttpServer HttpServer;
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700153 void IgnoreServerAborting(HttpServer* server) const {
154 PythonHttpServer *pyserver = reinterpret_cast<PythonHttpServer*>(server);
155 pyserver->validate_quit_ = false;
156 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000157};
158
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700159template <>
160class HttpFetcherTest<MultiHttpFetcher<LibcurlHttpFetcher> >
161 : public HttpFetcherTest<LibcurlHttpFetcher> {
162 public:
163 HttpFetcher* NewLargeFetcher() {
164 MultiHttpFetcher<LibcurlHttpFetcher> *ret =
165 new MultiHttpFetcher<LibcurlHttpFetcher>;
166 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect
167 ranges(1, make_pair(0, -1));
168 ret->set_ranges(ranges);
169 // Speed up test execution.
170 ret->set_idle_seconds(1);
171 ret->set_retry_seconds(1);
172 return ret;
173 }
174 bool IsMulti() const { return true; }
175};
176
177typedef ::testing::Types<LibcurlHttpFetcher,
178 MockHttpFetcher,
179 MultiHttpFetcher<LibcurlHttpFetcher> >
180HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000181TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
182
183namespace {
184class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000185 public:
rspangler@google.com49fdf182009-10-10 00:57:34 +0000186 virtual void ReceivedBytes(HttpFetcher* fetcher,
187 const char* bytes, int length) {
188 char str[length + 1];
189 memset(str, 0, length + 1);
190 memcpy(str, bytes, length);
191 }
192 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Darin Petkovcb466212010-08-26 09:40:11 -0700193 EXPECT_EQ(200, fetcher->http_response_code());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000194 g_main_loop_quit(loop_);
195 }
196 GMainLoop* loop_;
197};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000198
199struct StartTransferArgs {
200 HttpFetcher *http_fetcher;
201 string url;
202};
203
204gboolean StartTransfer(gpointer data) {
205 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
206 args->http_fetcher->BeginTransfer(args->url);
207 return FALSE;
208}
rspangler@google.com49fdf182009-10-10 00:57:34 +0000209} // namespace {}
210
211TYPED_TEST(HttpFetcherTest, SimpleTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700212 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000213 {
214 HttpFetcherTestDelegate delegate;
215 delegate.loop_ = loop;
216 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
217 fetcher->set_delegate(&delegate);
218
219 typename TestFixture::HttpServer server;
220 ASSERT_TRUE(server.started_);
221
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000222 StartTransferArgs start_xfer_args = {fetcher.get(), this->SmallUrl()};
223
224 g_timeout_add(0, StartTransfer, &start_xfer_args);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000225 g_main_loop_run(loop);
226 }
227 g_main_loop_unref(loop);
228}
229
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700230TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700231 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700232 {
233 HttpFetcherTestDelegate delegate;
234 delegate.loop_ = loop;
235 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
236 fetcher->set_delegate(&delegate);
237
238 typename TestFixture::HttpServer server;
239 ASSERT_TRUE(server.started_);
240
241 StartTransferArgs start_xfer_args = {fetcher.get(), this->BigUrl()};
242
243 g_timeout_add(0, StartTransfer, &start_xfer_args);
244 g_main_loop_run(loop);
245 }
246 g_main_loop_unref(loop);
247}
248
rspangler@google.com49fdf182009-10-10 00:57:34 +0000249namespace {
250class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
251 public:
252 virtual void ReceivedBytes(HttpFetcher* fetcher,
253 const char* bytes, int length) {
254 char str[length + 1];
rspangler@google.com49fdf182009-10-10 00:57:34 +0000255 memset(str, 0, length + 1);
256 memcpy(str, bytes, length);
257 CHECK(!paused_);
258 paused_ = true;
259 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000260 }
261 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
262 g_main_loop_quit(loop_);
263 }
264 void Unpause() {
265 CHECK(paused_);
266 paused_ = false;
267 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000268 }
269 bool paused_;
270 HttpFetcher* fetcher_;
271 GMainLoop* loop_;
272};
273
274gboolean UnpausingTimeoutCallback(gpointer data) {
275 PausingHttpFetcherTestDelegate *delegate =
276 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data);
277 if (delegate->paused_)
278 delegate->Unpause();
279 return TRUE;
280}
281} // namespace {}
282
283TYPED_TEST(HttpFetcherTest, PauseTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700284 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000285 {
286 PausingHttpFetcherTestDelegate delegate;
287 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
288 delegate.paused_ = false;
289 delegate.loop_ = loop;
290 delegate.fetcher_ = fetcher.get();
291 fetcher->set_delegate(&delegate);
292
293 typename TestFixture::HttpServer server;
294 ASSERT_TRUE(server.started_);
295 GSource* timeout_source_;
296 timeout_source_ = g_timeout_source_new(0); // ms
297 g_source_set_callback(timeout_source_, UnpausingTimeoutCallback, &delegate,
298 NULL);
299 g_source_attach(timeout_source_, NULL);
300 fetcher->BeginTransfer(this->BigUrl());
301
302 g_main_loop_run(loop);
303 g_source_destroy(timeout_source_);
304 }
305 g_main_loop_unref(loop);
306}
307
308namespace {
309class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
310 public:
311 virtual void ReceivedBytes(HttpFetcher* fetcher,
312 const char* bytes, int length) {}
313 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
314 CHECK(false); // We should never get here
315 g_main_loop_quit(loop_);
316 }
317 void TerminateTransfer() {
318 CHECK(once_);
319 once_ = false;
320 fetcher_->TerminateTransfer();
321 }
322 void EndLoop() {
323 g_main_loop_quit(loop_);
324 }
325 bool once_;
326 HttpFetcher* fetcher_;
327 GMainLoop* loop_;
328};
329
330gboolean AbortingTimeoutCallback(gpointer data) {
331 AbortingHttpFetcherTestDelegate *delegate =
332 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
333 if (delegate->once_) {
334 delegate->TerminateTransfer();
335 return TRUE;
336 } else {
337 delegate->EndLoop();
338 return FALSE;
339 }
340}
341} // namespace {}
342
343TYPED_TEST(HttpFetcherTest, AbortTest) {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700344 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000345 {
346 AbortingHttpFetcherTestDelegate delegate;
347 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
348 delegate.once_ = true;
349 delegate.loop_ = loop;
350 delegate.fetcher_ = fetcher.get();
351 fetcher->set_delegate(&delegate);
352
353 typename TestFixture::HttpServer server;
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700354 this->IgnoreServerAborting(&server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000355 ASSERT_TRUE(server.started_);
356 GSource* timeout_source_;
357 timeout_source_ = g_timeout_source_new(0); // ms
358 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
359 NULL);
360 g_source_attach(timeout_source_, NULL);
361 fetcher->BeginTransfer(this->BigUrl());
362
363 g_main_loop_run(loop);
364 g_source_destroy(timeout_source_);
365 }
366 g_main_loop_unref(loop);
367}
368
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000369namespace {
370class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
371 public:
372 virtual void ReceivedBytes(HttpFetcher* fetcher,
373 const char* bytes, int length) {
374 data.append(bytes, length);
375 }
376 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700377 EXPECT_TRUE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700378 EXPECT_EQ(206, fetcher->http_response_code());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000379 g_main_loop_quit(loop_);
380 }
381 string data;
382 GMainLoop* loop_;
383};
384} // namespace {}
385
386TYPED_TEST(HttpFetcherTest, FlakyTest) {
387 if (this->IsMock())
388 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700389 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000390 {
391 FlakyHttpFetcherTestDelegate delegate;
392 delegate.loop_ = loop;
393 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
394 fetcher->set_delegate(&delegate);
395
396 typename TestFixture::HttpServer server;
397 ASSERT_TRUE(server.started_);
398
399 StartTransferArgs start_xfer_args = {
400 fetcher.get(),
401 LocalServerUrlForPath("/flaky")
402 };
403
404 g_timeout_add(0, StartTransfer, &start_xfer_args);
405 g_main_loop_run(loop);
406
407 // verify the data we get back
408 ASSERT_EQ(100000, delegate.data.size());
409 for (int i = 0; i < 100000; i += 10) {
410 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
411 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
412 }
413 }
414 g_main_loop_unref(loop);
415}
416
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700417namespace {
418class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
419 public:
420 FailureHttpFetcherTestDelegate() : loop_(NULL), server_(NULL) {}
421 virtual void ReceivedBytes(HttpFetcher* fetcher,
422 const char* bytes, int length) {
423 if (server_) {
424 LOG(INFO) << "Stopping server";
425 delete server_;
426 LOG(INFO) << "server stopped";
427 server_ = NULL;
428 }
429 }
430 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
431 EXPECT_FALSE(successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700432 EXPECT_EQ(0, fetcher->http_response_code());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700433 g_main_loop_quit(loop_);
434 }
435 GMainLoop* loop_;
436 PythonHttpServer* server_;
437};
438} // namespace {}
439
440
441TYPED_TEST(HttpFetcherTest, FailureTest) {
442 if (this->IsMock())
443 return;
444 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
445 {
446 FailureHttpFetcherTestDelegate delegate;
447 delegate.loop_ = loop;
448 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
449 fetcher->set_delegate(&delegate);
450
451 StartTransferArgs start_xfer_args = {
452 fetcher.get(),
453 LocalServerUrlForPath(this->SmallUrl())
454 };
455
456 g_timeout_add(0, StartTransfer, &start_xfer_args);
457 g_main_loop_run(loop);
458
459 // Exiting and testing happens in the delegate
460 }
461 g_main_loop_unref(loop);
462}
463
464TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
465 if (this->IsMock())
466 return;
467 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
468 {
469 FailureHttpFetcherTestDelegate delegate;
470 delegate.loop_ = loop;
471 delegate.server_ = new PythonHttpServer;
472 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher());
473 fetcher->set_delegate(&delegate);
474
475 StartTransferArgs start_xfer_args = {
476 fetcher.get(),
477 LocalServerUrlForPath("/flaky")
478 };
479
480 g_timeout_add(0, StartTransfer, &start_xfer_args);
481 g_main_loop_run(loop);
482
483 // Exiting and testing happens in the delegate
484 }
485 g_main_loop_unref(loop);
486}
487
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700488namespace {
489const int kRedirectCodes[] = { 301, 302, 303, 307 };
490
491class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
492 public:
493 RedirectHttpFetcherTestDelegate(bool expected_successful)
494 : expected_successful_(expected_successful) {}
495 virtual void ReceivedBytes(HttpFetcher* fetcher,
496 const char* bytes, int length) {
497 data.append(bytes, length);
498 }
499 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
500 EXPECT_EQ(expected_successful_, successful);
Darin Petkovcb466212010-08-26 09:40:11 -0700501 if (expected_successful_)
502 EXPECT_EQ(200, fetcher->http_response_code());
503 else {
504 EXPECT_GE(fetcher->http_response_code(), 301);
505 EXPECT_LE(fetcher->http_response_code(), 307);
506 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700507 g_main_loop_quit(loop_);
508 }
509 bool expected_successful_;
510 string data;
511 GMainLoop* loop_;
512};
513
514// RedirectTest takes ownership of |http_fetcher|.
515void RedirectTest(bool expected_successful,
516 const string& url,
517 HttpFetcher* http_fetcher) {
518 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
519 RedirectHttpFetcherTestDelegate delegate(expected_successful);
520 delegate.loop_ = loop;
521 scoped_ptr<HttpFetcher> fetcher(http_fetcher);
522 fetcher->set_delegate(&delegate);
523
524 StartTransferArgs start_xfer_args =
525 { fetcher.get(), LocalServerUrlForPath(url) };
526
527 g_timeout_add(0, StartTransfer, &start_xfer_args);
528 g_main_loop_run(loop);
529 if (expected_successful) {
530 // verify the data we get back
531 ASSERT_EQ(1000, delegate.data.size());
532 for (int i = 0; i < 1000; i += 10) {
533 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
534 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
535 }
536 }
537 g_main_loop_unref(loop);
538}
539} // namespace {}
540
541TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
542 if (this->IsMock())
543 return;
544 typename TestFixture::HttpServer server;
545 ASSERT_TRUE(server.started_);
546 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
547 const string url = base::StringPrintf("/redirect/%d/medium",
548 kRedirectCodes[c]);
549 RedirectTest(true, url, this->NewLargeFetcher());
550 }
551}
552
553TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
554 if (this->IsMock())
555 return;
556 typename TestFixture::HttpServer server;
557 ASSERT_TRUE(server.started_);
558 string url;
559 for (int r = 0; r < LibcurlHttpFetcher::kMaxRedirects; r++) {
560 url += base::StringPrintf("/redirect/%d",
561 kRedirectCodes[r % arraysize(kRedirectCodes)]);
562 }
563 url += "/medium";
564 RedirectTest(true, url, this->NewLargeFetcher());
565}
566
567TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
568 if (this->IsMock())
569 return;
570 typename TestFixture::HttpServer server;
571 ASSERT_TRUE(server.started_);
572 string url;
573 for (int r = 0; r < LibcurlHttpFetcher::kMaxRedirects + 1; r++) {
574 url += base::StringPrintf("/redirect/%d",
575 kRedirectCodes[r % arraysize(kRedirectCodes)]);
576 }
577 url += "/medium";
578 RedirectTest(false, url, this->NewLargeFetcher());
579}
580
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700581namespace {
582class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
583 public:
584 MultiHttpFetcherTestDelegate(int expected_response_code)
585 : expected_response_code_(expected_response_code) {}
586 virtual void ReceivedBytes(HttpFetcher* fetcher,
587 const char* bytes, int length) {
588 data.append(bytes, length);
589 }
590 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
591 EXPECT_EQ(expected_response_code_ != 0, successful);
592 if (expected_response_code_ != 0)
593 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
594 g_main_loop_quit(loop_);
595 }
596 int expected_response_code_;
597 string data;
598 GMainLoop* loop_;
599};
600
601void MultiTest(HttpFetcher* fetcher_in,
602 const string& url,
603 const MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect& ranges,
604 const string& expected_prefix,
605 off_t expected_size,
606 int expected_response_code) {
607 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
608 {
609 MultiHttpFetcherTestDelegate delegate(expected_response_code);
610 delegate.loop_ = loop;
611 scoped_ptr<HttpFetcher> fetcher(fetcher_in);
612 MultiHttpFetcher<LibcurlHttpFetcher>* multi_fetcher =
613 dynamic_cast<MultiHttpFetcher<LibcurlHttpFetcher>*>(fetcher.get());
614 ASSERT_TRUE(multi_fetcher);
615 multi_fetcher->set_ranges(ranges);
616 fetcher->set_delegate(&delegate);
617
618 StartTransferArgs start_xfer_args = {fetcher.get(), url};
619
620 g_timeout_add(0, StartTransfer, &start_xfer_args);
621 g_main_loop_run(loop);
622
623 EXPECT_EQ(expected_size, delegate.data.size());
624 EXPECT_EQ(expected_prefix,
625 string(delegate.data.data(), expected_prefix.size()));
626 }
627 g_main_loop_unref(loop);
628}
629} // namespace {}
630
631TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimplTest) {
632 if (!this->IsMulti())
633 return;
634 typename TestFixture::HttpServer server;
635 ASSERT_TRUE(server.started_);
636
637 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
638 ranges.push_back(make_pair(0, 25));
639 ranges.push_back(make_pair(99, -1));
640 MultiTest(this->NewLargeFetcher(),
641 this->BigUrl(),
642 ranges,
643 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
644 kBigSize - (99 - 25),
645 206);
646}
647
648TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
649 if (!this->IsMulti())
650 return;
651 typename TestFixture::HttpServer server;
652 ASSERT_TRUE(server.started_);
653
654 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
655 ranges.push_back(make_pair(0, 24));
656 MultiTest(this->NewLargeFetcher(),
657 this->BigUrl(),
658 ranges,
659 "abcdefghijabcdefghijabcd",
660 24,
661 200);
662}
663
664TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
665 if (!this->IsMulti())
666 return;
667 typename TestFixture::HttpServer server;
668 ASSERT_TRUE(server.started_);
669
670 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
671 ranges.push_back(make_pair(kBigSize - 2, -1));
672 ranges.push_back(make_pair(kBigSize - 3, -1));
673 MultiTest(this->NewLargeFetcher(),
674 this->BigUrl(),
675 ranges,
676 "ijhij",
677 5,
678 206);
679}
680
681TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
682 if (!this->IsMulti())
683 return;
684 typename TestFixture::HttpServer server;
685 ASSERT_TRUE(server.started_);
686
687 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
688 ranges.push_back(make_pair(kBigSize - 2, 4));
689 for (int i = 0; i < 2; ++i) {
690 MultiTest(this->NewLargeFetcher(),
691 this->BigUrl(),
692 ranges,
693 "ij",
694 2,
695 0);
696 ranges.push_back(make_pair(0, 5));
697 }
698}
699
Andrew de los Reyesd57d1472010-10-21 13:34:08 -0700700namespace {
701class ExpensiveConnectionTestDelegate : public HttpFetcherDelegate {
702 public:
703 virtual void ReceivedBytes(HttpFetcher* fetcher,
704 const char* bytes, int length) {
705 ADD_FAILURE();
706 }
707 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
708 EXPECT_FALSE(successful);
709 g_main_loop_quit(loop_);
710 }
711 GMainLoop* loop_;
712};
713
714} // namespace
715
716TYPED_TEST(HttpFetcherTest, ExpensiveConnectionTest) {
717 if (this->IsMock() || this->IsMulti())
718 return;
719 typename TestFixture::HttpServer server;
720
721 ASSERT_TRUE(server.started_);
722
723 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
724 ExpensiveConnectionTestDelegate delegate;
725 delegate.loop_ = loop;
726
727 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher());
728 dynamic_cast<LibcurlHttpFetcher*>(
729 fetcher.get())->SetConnectionAsExpensive(true);
730 fetcher->set_delegate(&delegate);
731
732 StartTransferArgs start_xfer_args =
733 { fetcher.get(), LocalServerUrlForPath(this->SmallUrl()) };
734
735 g_timeout_add(0, StartTransfer, &start_xfer_args);
736 g_main_loop_run(loop);
737 g_main_loop_unref(loop);
738}
739
rspangler@google.com49fdf182009-10-10 00:57:34 +0000740} // namespace chromeos_update_engine