Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Side by Side Diff: http_fetcher_unittest.cc

Issue 5009009: AU: Fix potential issues with premature destruction of HTTP fetchers. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/update_engine.git@master
Patch Set: review comments Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « http_fetcher.h ('k') | libcurl_http_fetcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. 1 // 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <unistd.h> 5 #include <unistd.h>
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 virtual void ReceivedBytes(HttpFetcher* fetcher, 189 virtual void ReceivedBytes(HttpFetcher* fetcher,
190 const char* bytes, int length) { 190 const char* bytes, int length) {
191 char str[length + 1]; 191 char str[length + 1];
192 memset(str, 0, length + 1); 192 memset(str, 0, length + 1);
193 memcpy(str, bytes, length); 193 memcpy(str, bytes, length);
194 } 194 }
195 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { 195 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
196 EXPECT_EQ(200, fetcher->http_response_code()); 196 EXPECT_EQ(200, fetcher->http_response_code());
197 g_main_loop_quit(loop_); 197 g_main_loop_quit(loop_);
198 } 198 }
199 virtual void TransferTerminated(HttpFetcher* fetcher) {
200 ADD_FAILURE();
201 }
199 GMainLoop* loop_; 202 GMainLoop* loop_;
200 }; 203 };
201 204
202 struct StartTransferArgs { 205 struct StartTransferArgs {
203 HttpFetcher *http_fetcher; 206 HttpFetcher *http_fetcher;
204 string url; 207 string url;
205 }; 208 };
206 209
207 gboolean StartTransfer(gpointer data) { 210 gboolean StartTransfer(gpointer data) {
208 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data); 211 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 char str[length + 1]; 260 char str[length + 1];
258 memset(str, 0, length + 1); 261 memset(str, 0, length + 1);
259 memcpy(str, bytes, length); 262 memcpy(str, bytes, length);
260 CHECK(!paused_); 263 CHECK(!paused_);
261 paused_ = true; 264 paused_ = true;
262 fetcher->Pause(); 265 fetcher->Pause();
263 } 266 }
264 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { 267 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
265 g_main_loop_quit(loop_); 268 g_main_loop_quit(loop_);
266 } 269 }
270 virtual void TransferTerminated(HttpFetcher* fetcher) {
271 ADD_FAILURE();
272 }
267 void Unpause() { 273 void Unpause() {
268 CHECK(paused_); 274 CHECK(paused_);
269 paused_ = false; 275 paused_ = false;
270 fetcher_->Unpause(); 276 fetcher_->Unpause();
271 } 277 }
272 bool paused_; 278 bool paused_;
273 HttpFetcher* fetcher_; 279 HttpFetcher* fetcher_;
274 GMainLoop* loop_; 280 GMainLoop* loop_;
275 }; 281 };
276 282
(...skipping 30 matching lines...) Expand all
307 } 313 }
308 g_main_loop_unref(loop); 314 g_main_loop_unref(loop);
309 } 315 }
310 316
311 namespace { 317 namespace {
312 class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate { 318 class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
313 public: 319 public:
314 virtual void ReceivedBytes(HttpFetcher* fetcher, 320 virtual void ReceivedBytes(HttpFetcher* fetcher,
315 const char* bytes, int length) {} 321 const char* bytes, int length) {}
316 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { 322 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
317 CHECK(false); // We should never get here 323 ADD_FAILURE(); // We should never get here
318 g_main_loop_quit(loop_); 324 g_main_loop_quit(loop_);
319 } 325 }
326 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 }
320 void TerminateTransfer() { 334 void TerminateTransfer() {
321 CHECK(once_); 335 CHECK(once_);
322 once_ = false; 336 once_ = false;
323 fetcher_->TerminateTransfer(); 337 fetcher_->TerminateTransfer();
324 } 338 }
325 void EndLoop() { 339 void EndLoop() {
326 g_main_loop_quit(loop_); 340 g_main_loop_quit(loop_);
327 } 341 }
328 bool once_; 342 bool once_;
329 HttpFetcher* fetcher_; 343 bool callback_once_;
344 scoped_ptr<HttpFetcher> fetcher_;
330 GMainLoop* loop_; 345 GMainLoop* loop_;
331 }; 346 };
332 347
333 gboolean AbortingTimeoutCallback(gpointer data) { 348 gboolean AbortingTimeoutCallback(gpointer data) {
334 AbortingHttpFetcherTestDelegate *delegate = 349 AbortingHttpFetcherTestDelegate *delegate =
335 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data); 350 reinterpret_cast<AbortingHttpFetcherTestDelegate*>(data);
336 if (delegate->once_) { 351 if (delegate->once_) {
337 delegate->TerminateTransfer(); 352 delegate->TerminateTransfer();
338 return TRUE; 353 return TRUE;
339 } else { 354 } else {
340 delegate->EndLoop(); 355 delegate->EndLoop();
341 return FALSE; 356 return FALSE;
342 } 357 }
343 } 358 }
344 } // namespace {} 359 } // namespace {}
345 360
346 TYPED_TEST(HttpFetcherTest, AbortTest) { 361 TYPED_TEST(HttpFetcherTest, AbortTest) {
347 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE); 362 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
348 { 363 {
349 AbortingHttpFetcherTestDelegate delegate; 364 AbortingHttpFetcherTestDelegate delegate;
350 scoped_ptr<HttpFetcher> fetcher(this->NewLargeFetcher()); 365 delegate.fetcher_.reset(this->NewLargeFetcher());
351 delegate.once_ = true; 366 delegate.once_ = true;
367 delegate.callback_once_ = true;
352 delegate.loop_ = loop; 368 delegate.loop_ = loop;
353 delegate.fetcher_ = fetcher.get(); 369 delegate.fetcher_->set_delegate(&delegate);
354 fetcher->set_delegate(&delegate);
355 370
356 typename TestFixture::HttpServer server; 371 typename TestFixture::HttpServer server;
357 this->IgnoreServerAborting(&server); 372 this->IgnoreServerAborting(&server);
358 ASSERT_TRUE(server.started_); 373 ASSERT_TRUE(server.started_);
359 GSource* timeout_source_; 374 GSource* timeout_source_;
360 timeout_source_ = g_timeout_source_new(0); // ms 375 timeout_source_ = g_timeout_source_new(0); // ms
361 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate, 376 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
362 NULL); 377 NULL);
363 g_source_attach(timeout_source_, NULL); 378 g_source_attach(timeout_source_, NULL);
364 fetcher->BeginTransfer(this->BigUrl()); 379 delegate.fetcher_->BeginTransfer(this->BigUrl());
365 380
366 g_main_loop_run(loop); 381 g_main_loop_run(loop);
382 CHECK(!delegate.once_);
383 CHECK(!delegate.callback_once_);
367 g_source_destroy(timeout_source_); 384 g_source_destroy(timeout_source_);
368 } 385 }
369 g_main_loop_unref(loop); 386 g_main_loop_unref(loop);
370 } 387 }
371 388
372 namespace { 389 namespace {
373 class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate { 390 class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
374 public: 391 public:
375 virtual void ReceivedBytes(HttpFetcher* fetcher, 392 virtual void ReceivedBytes(HttpFetcher* fetcher,
376 const char* bytes, int length) { 393 const char* bytes, int length) {
377 data.append(bytes, length); 394 data.append(bytes, length);
378 } 395 }
379 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { 396 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
380 EXPECT_TRUE(successful); 397 EXPECT_TRUE(successful);
381 EXPECT_EQ(206, fetcher->http_response_code()); 398 EXPECT_EQ(206, fetcher->http_response_code());
382 g_main_loop_quit(loop_); 399 g_main_loop_quit(loop_);
383 } 400 }
401 virtual void TransferTerminated(HttpFetcher* fetcher) {
402 ADD_FAILURE();
403 }
384 string data; 404 string data;
385 GMainLoop* loop_; 405 GMainLoop* loop_;
386 }; 406 };
387 } // namespace {} 407 } // namespace {}
388 408
389 TYPED_TEST(HttpFetcherTest, FlakyTest) { 409 TYPED_TEST(HttpFetcherTest, FlakyTest) {
390 if (this->IsMock()) 410 if (this->IsMock())
391 return; 411 return;
392 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE); 412 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
393 { 413 {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 delete server_; 448 delete server_;
429 LOG(INFO) << "server stopped"; 449 LOG(INFO) << "server stopped";
430 server_ = NULL; 450 server_ = NULL;
431 } 451 }
432 } 452 }
433 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { 453 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
434 EXPECT_FALSE(successful); 454 EXPECT_FALSE(successful);
435 EXPECT_EQ(0, fetcher->http_response_code()); 455 EXPECT_EQ(0, fetcher->http_response_code());
436 g_main_loop_quit(loop_); 456 g_main_loop_quit(loop_);
437 } 457 }
458 virtual void TransferTerminated(HttpFetcher* fetcher) {
459 ADD_FAILURE();
460 }
438 GMainLoop* loop_; 461 GMainLoop* loop_;
439 PythonHttpServer* server_; 462 PythonHttpServer* server_;
440 }; 463 };
441 } // namespace {} 464 } // namespace {}
442 465
443 466
444 TYPED_TEST(HttpFetcherTest, FailureTest) { 467 TYPED_TEST(HttpFetcherTest, FailureTest) {
445 if (this->IsMock()) 468 if (this->IsMock())
446 return; 469 return;
447 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE); 470 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { 525 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
503 EXPECT_EQ(expected_successful_, successful); 526 EXPECT_EQ(expected_successful_, successful);
504 if (expected_successful_) 527 if (expected_successful_)
505 EXPECT_EQ(200, fetcher->http_response_code()); 528 EXPECT_EQ(200, fetcher->http_response_code());
506 else { 529 else {
507 EXPECT_GE(fetcher->http_response_code(), 301); 530 EXPECT_GE(fetcher->http_response_code(), 301);
508 EXPECT_LE(fetcher->http_response_code(), 307); 531 EXPECT_LE(fetcher->http_response_code(), 307);
509 } 532 }
510 g_main_loop_quit(loop_); 533 g_main_loop_quit(loop_);
511 } 534 }
535 virtual void TransferTerminated(HttpFetcher* fetcher) {
536 ADD_FAILURE();
537 }
512 bool expected_successful_; 538 bool expected_successful_;
513 string data; 539 string data;
514 GMainLoop* loop_; 540 GMainLoop* loop_;
515 }; 541 };
516 542
517 // RedirectTest takes ownership of |http_fetcher|. 543 // RedirectTest takes ownership of |http_fetcher|.
518 void RedirectTest(bool expected_successful, 544 void RedirectTest(bool expected_successful,
519 const string& url, 545 const string& url,
520 HttpFetcher* http_fetcher) { 546 HttpFetcher* http_fetcher) {
521 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE); 547 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 RedirectTest(false, url, this->NewLargeFetcher()); 607 RedirectTest(false, url, this->NewLargeFetcher());
582 } 608 }
583 609
584 namespace { 610 namespace {
585 class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate { 611 class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
586 public: 612 public:
587 MultiHttpFetcherTestDelegate(int expected_response_code) 613 MultiHttpFetcherTestDelegate(int expected_response_code)
588 : expected_response_code_(expected_response_code) {} 614 : expected_response_code_(expected_response_code) {}
589 virtual void ReceivedBytes(HttpFetcher* fetcher, 615 virtual void ReceivedBytes(HttpFetcher* fetcher,
590 const char* bytes, int length) { 616 const char* bytes, int length) {
617 EXPECT_EQ(fetcher, fetcher_.get());
591 data.append(bytes, length); 618 data.append(bytes, length);
592 } 619 }
593 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { 620 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
621 EXPECT_EQ(fetcher, fetcher_.get());
594 EXPECT_EQ(expected_response_code_ != 0, successful); 622 EXPECT_EQ(expected_response_code_ != 0, successful);
595 if (expected_response_code_ != 0) 623 if (expected_response_code_ != 0)
596 EXPECT_EQ(expected_response_code_, fetcher->http_response_code()); 624 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
625 // Destroy the fetcher (because we're allowed to).
626 fetcher_.reset(NULL);
597 g_main_loop_quit(loop_); 627 g_main_loop_quit(loop_);
598 } 628 }
629 virtual void TransferTerminated(HttpFetcher* fetcher) {
630 ADD_FAILURE();
631 }
632 scoped_ptr<HttpFetcher> fetcher_;
599 int expected_response_code_; 633 int expected_response_code_;
600 string data; 634 string data;
601 GMainLoop* loop_; 635 GMainLoop* loop_;
602 }; 636 };
603 637
604 void MultiTest(HttpFetcher* fetcher_in, 638 void MultiTest(HttpFetcher* fetcher_in,
605 const string& url, 639 const string& url,
606 const MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect& ranges, 640 const MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect& ranges,
607 const string& expected_prefix, 641 const string& expected_prefix,
608 off_t expected_size, 642 off_t expected_size,
609 int expected_response_code) { 643 int expected_response_code) {
610 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE); 644 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
611 { 645 {
612 MultiHttpFetcherTestDelegate delegate(expected_response_code); 646 MultiHttpFetcherTestDelegate delegate(expected_response_code);
613 delegate.loop_ = loop; 647 delegate.loop_ = loop;
614 scoped_ptr<HttpFetcher> fetcher(fetcher_in); 648 delegate.fetcher_.reset(fetcher_in);
615 MultiHttpFetcher<LibcurlHttpFetcher>* multi_fetcher = 649 MultiHttpFetcher<LibcurlHttpFetcher>* multi_fetcher =
616 dynamic_cast<MultiHttpFetcher<LibcurlHttpFetcher>*>(fetcher.get()); 650 dynamic_cast<MultiHttpFetcher<LibcurlHttpFetcher>*>(fetcher_in);
617 ASSERT_TRUE(multi_fetcher); 651 ASSERT_TRUE(multi_fetcher);
618 multi_fetcher->set_ranges(ranges); 652 multi_fetcher->set_ranges(ranges);
619 multi_fetcher->SetConnectionAsExpensive(false); 653 multi_fetcher->SetConnectionAsExpensive(false);
620 multi_fetcher->SetBuildType(false); 654 multi_fetcher->SetBuildType(false);
621 fetcher->set_delegate(&delegate); 655 multi_fetcher->set_delegate(&delegate);
622 656
623 StartTransferArgs start_xfer_args = {fetcher.get(), url}; 657 StartTransferArgs start_xfer_args = {multi_fetcher, url};
624 658
625 g_timeout_add(0, StartTransfer, &start_xfer_args); 659 g_timeout_add(0, StartTransfer, &start_xfer_args);
626 g_main_loop_run(loop); 660 g_main_loop_run(loop);
627 661
628 EXPECT_EQ(expected_size, delegate.data.size()); 662 EXPECT_EQ(expected_size, delegate.data.size());
629 EXPECT_EQ(expected_prefix, 663 EXPECT_EQ(expected_prefix,
630 string(delegate.data.data(), expected_prefix.size())); 664 string(delegate.data.data(), expected_prefix.size()));
631 } 665 }
632 g_main_loop_unref(loop); 666 g_main_loop_unref(loop);
633 } 667 }
634 } // namespace {} 668 } // namespace {}
635 669
636 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimplTest) { 670 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
637 if (!this->IsMulti()) 671 if (!this->IsMulti())
638 return; 672 return;
639 typename TestFixture::HttpServer server; 673 typename TestFixture::HttpServer server;
640 ASSERT_TRUE(server.started_); 674 ASSERT_TRUE(server.started_);
641 675
642 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges; 676 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
643 ranges.push_back(make_pair(0, 25)); 677 ranges.push_back(make_pair(0, 25));
644 ranges.push_back(make_pair(99, -1)); 678 ranges.push_back(make_pair(99, -1));
645 MultiTest(this->NewLargeFetcher(), 679 MultiTest(this->NewLargeFetcher(),
646 this->BigUrl(), 680 this->BigUrl(),
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 class BlockedTransferTestDelegate : public HttpFetcherDelegate { 740 class BlockedTransferTestDelegate : public HttpFetcherDelegate {
707 public: 741 public:
708 virtual void ReceivedBytes(HttpFetcher* fetcher, 742 virtual void ReceivedBytes(HttpFetcher* fetcher,
709 const char* bytes, int length) { 743 const char* bytes, int length) {
710 ADD_FAILURE(); 744 ADD_FAILURE();
711 } 745 }
712 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { 746 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
713 EXPECT_FALSE(successful); 747 EXPECT_FALSE(successful);
714 g_main_loop_quit(loop_); 748 g_main_loop_quit(loop_);
715 } 749 }
750 virtual void TransferTerminated(HttpFetcher* fetcher) {
751 ADD_FAILURE();
752 }
716 GMainLoop* loop_; 753 GMainLoop* loop_;
717 }; 754 };
718 755
719 } // namespace 756 } // namespace
720 757
721 TYPED_TEST(HttpFetcherTest, BlockedTransferTest) { 758 TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
722 if (this->IsMock() || this->IsMulti()) 759 if (this->IsMock() || this->IsMulti())
723 return; 760 return;
724 761
725 for (int i = 0; i < 2; i++) { 762 for (int i = 0; i < 2; i++) {
(...skipping 19 matching lines...) Expand all
745 StartTransferArgs start_xfer_args = 782 StartTransferArgs start_xfer_args =
746 { fetcher.get(), LocalServerUrlForPath(this->SmallUrl()) }; 783 { fetcher.get(), LocalServerUrlForPath(this->SmallUrl()) };
747 784
748 g_timeout_add(0, StartTransfer, &start_xfer_args); 785 g_timeout_add(0, StartTransfer, &start_xfer_args);
749 g_main_loop_run(loop); 786 g_main_loop_run(loop);
750 g_main_loop_unref(loop); 787 g_main_loop_unref(loop);
751 } 788 }
752 } 789 }
753 790
754 } // namespace chromeos_update_engine 791 } // namespace chromeos_update_engine
OLDNEW
« no previous file with comments | « http_fetcher.h ('k') | libcurl_http_fetcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698