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