1 // 2 // Copyright (C) 2012 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include <netinet/in.h> 18 #include <netinet/ip.h> 19 #include <sys/socket.h> 20 #include <unistd.h> 21 22 #include <memory> 23 #include <string> 24 #include <utility> 25 #include <vector> 26 27 #include <base/bind.h> 28 #include <base/location.h> 29 #include <base/logging.h> 30 #include <base/message_loop/message_loop.h> 31 #include <base/strings/string_number_conversions.h> 32 #include <base/strings/string_util.h> 33 #include <base/strings/stringprintf.h> 34 #include <base/time/time.h> 35 #include <brillo/message_loops/base_message_loop.h> 36 #include <brillo/message_loops/message_loop.h> 37 #include <brillo/message_loops/message_loop_utils.h> 38 #include <brillo/process.h> 39 #include <brillo/streams/file_stream.h> 40 #include <brillo/streams/stream.h> 41 #include <gtest/gtest.h> 42 43 #include "update_engine/common/fake_hardware.h" 44 #include "update_engine/common/file_fetcher.h" 45 #include "update_engine/common/http_common.h" 46 #include "update_engine/common/mock_http_fetcher.h" 47 #include "update_engine/common/multi_range_http_fetcher.h" 48 #include "update_engine/common/test_utils.h" 49 #include "update_engine/common/utils.h" 50 #include "update_engine/libcurl_http_fetcher.h" 51 #include "update_engine/mock_proxy_resolver.h" 52 #include "update_engine/proxy_resolver.h" 53 54 using brillo::MessageLoop; 55 using std::make_pair; 56 using std::pair; 57 using std::string; 58 using std::unique_ptr; 59 using std::vector; 60 using testing::DoAll; 61 using testing::Return; 62 using testing::SaveArg; 63 using testing::_; 64 65 namespace { 66 67 const int kBigLength = 100000; 68 const int kMediumLength = 1000; 69 const int kFlakyTruncateLength = 29000; 70 const int kFlakySleepEvery = 3; 71 const int kFlakySleepSecs = 10; 72 73 } // namespace 74 75 namespace chromeos_update_engine { 76 77 static const char *kUnusedUrl = "unused://unused"; 78 79 static inline string LocalServerUrlForPath(in_port_t port, 80 const string& path) { 81 string port_str = (port ? base::StringPrintf(":%hu", port) : ""); 82 return base::StringPrintf("http://127.0.0.1%s%s", port_str.c_str(), 83 path.c_str()); 84 } 85 86 // 87 // Class hierarchy for HTTP server implementations. 88 // 89 90 class HttpServer { 91 public: 92 // This makes it an abstract class (dirty but works). 93 virtual ~HttpServer() = 0; 94 95 virtual in_port_t GetPort() const { 96 return 0; 97 } 98 99 bool started_; 100 }; 101 102 HttpServer::~HttpServer() {} 103 104 105 class NullHttpServer : public HttpServer { 106 public: 107 NullHttpServer() { 108 started_ = true; 109 } 110 }; 111 112 113 class PythonHttpServer : public HttpServer { 114 public: 115 PythonHttpServer() : port_(0) { 116 started_ = false; 117 118 // Spawn the server process. 119 unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl()); 120 http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server")); 121 http_server->RedirectUsingPipe(STDOUT_FILENO, false); 122 123 if (!http_server->Start()) { 124 ADD_FAILURE() << "failed to spawn http server process"; 125 return; 126 } 127 LOG(INFO) << "started http server with pid " << http_server->pid(); 128 129 // Wait for server to begin accepting connections, obtain its port. 130 brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor( 131 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr); 132 if (!stdout) 133 return; 134 135 vector<char> buf(128); 136 string line; 137 while (line.find('\n') == string::npos) { 138 size_t read; 139 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) { 140 ADD_FAILURE() << "error reading http server stdout"; 141 return; 142 } 143 line.append(buf.data(), read); 144 if (read == 0) 145 break; 146 } 147 // Parse the port from the output line. 148 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix); 149 if (line.size() < listening_msg_prefix_len) { 150 ADD_FAILURE() << "server output too short"; 151 return; 152 } 153 154 EXPECT_EQ(kServerListeningMsgPrefix, 155 line.substr(0, listening_msg_prefix_len)); 156 string port_str = line.substr(listening_msg_prefix_len); 157 port_str.resize(port_str.find('\n')); 158 EXPECT_TRUE(base::StringToUint(port_str, &port_)); 159 160 started_ = true; 161 LOG(INFO) << "server running, listening on port " << port_; 162 163 // Any failure before this point will SIGKILL the test server if started 164 // when the |http_server| goes out of scope. 165 http_server_ = std::move(http_server); 166 } 167 168 ~PythonHttpServer() { 169 // If there's no process, do nothing. 170 if (!http_server_) 171 return; 172 // Wait up to 10 seconds for the process to finish. Destroying the process 173 // will kill it with a SIGKILL otherwise. 174 http_server_->Kill(SIGTERM, 10); 175 } 176 177 in_port_t GetPort() const override { 178 return port_; 179 } 180 181 private: 182 static const char* kServerListeningMsgPrefix; 183 184 unique_ptr<brillo::Process> http_server_; 185 unsigned int port_; 186 }; 187 188 const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port "; 189 190 // 191 // Class hierarchy for HTTP fetcher test wrappers. 192 // 193 194 class AnyHttpFetcherTest { 195 public: 196 AnyHttpFetcherTest() {} 197 virtual ~AnyHttpFetcherTest() {} 198 199 virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0; 200 HttpFetcher* NewLargeFetcher(size_t num_proxies) { 201 proxy_resolver_.set_num_proxies(num_proxies); 202 return NewLargeFetcher(&proxy_resolver_); 203 } 204 HttpFetcher* NewLargeFetcher() { 205 return NewLargeFetcher(1); 206 } 207 208 virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0; 209 HttpFetcher* NewSmallFetcher() { 210 proxy_resolver_.set_num_proxies(1); 211 return NewSmallFetcher(&proxy_resolver_); 212 } 213 214 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; } 215 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; } 216 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; } 217 218 virtual bool IsMock() const = 0; 219 virtual bool IsMulti() const = 0; 220 virtual bool IsHttpSupported() const = 0; 221 222 virtual void IgnoreServerAborting(HttpServer* server) const {} 223 224 virtual HttpServer* CreateServer() = 0; 225 226 FakeHardware* fake_hardware() { 227 return &fake_hardware_; 228 } 229 230 protected: 231 DirectProxyResolver proxy_resolver_; 232 FakeHardware fake_hardware_; 233 }; 234 235 class MockHttpFetcherTest : public AnyHttpFetcherTest { 236 public: 237 // Necessary to unhide the definition in the base class. 238 using AnyHttpFetcherTest::NewLargeFetcher; 239 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override { 240 brillo::Blob big_data(1000000); 241 return new MockHttpFetcher( 242 big_data.data(), big_data.size(), proxy_resolver); 243 } 244 245 // Necessary to unhide the definition in the base class. 246 using AnyHttpFetcherTest::NewSmallFetcher; 247 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override { 248 return new MockHttpFetcher("x", 1, proxy_resolver); 249 } 250 251 bool IsMock() const override { return true; } 252 bool IsMulti() const override { return false; } 253 bool IsHttpSupported() const override { return true; } 254 255 HttpServer* CreateServer() override { 256 return new NullHttpServer; 257 } 258 }; 259 260 class LibcurlHttpFetcherTest : public AnyHttpFetcherTest { 261 public: 262 // Necessary to unhide the definition in the base class. 263 using AnyHttpFetcherTest::NewLargeFetcher; 264 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override { 265 LibcurlHttpFetcher* ret = 266 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_); 267 // Speed up test execution. 268 ret->set_idle_seconds(1); 269 ret->set_retry_seconds(1); 270 fake_hardware_.SetIsOfficialBuild(false); 271 return ret; 272 } 273 274 // Necessary to unhide the definition in the base class. 275 using AnyHttpFetcherTest::NewSmallFetcher; 276 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override { 277 return NewLargeFetcher(proxy_resolver); 278 } 279 280 string BigUrl(in_port_t port) const override { 281 return LocalServerUrlForPath(port, 282 base::StringPrintf("/download/%d", 283 kBigLength)); 284 } 285 string SmallUrl(in_port_t port) const override { 286 return LocalServerUrlForPath(port, "/foo"); 287 } 288 string ErrorUrl(in_port_t port) const override { 289 return LocalServerUrlForPath(port, "/error"); 290 } 291 292 bool IsMock() const override { return false; } 293 bool IsMulti() const override { return false; } 294 bool IsHttpSupported() const override { return true; } 295 296 void IgnoreServerAborting(HttpServer* server) const override { 297 // Nothing to do. 298 } 299 300 HttpServer* CreateServer() override { 301 return new PythonHttpServer; 302 } 303 }; 304 305 class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest { 306 public: 307 // Necessary to unhide the definition in the base class. 308 using AnyHttpFetcherTest::NewLargeFetcher; 309 HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) override { 310 MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher( 311 new LibcurlHttpFetcher(proxy_resolver, &fake_hardware_)); 312 ret->ClearRanges(); 313 ret->AddRange(0); 314 // Speed up test execution. 315 ret->set_idle_seconds(1); 316 ret->set_retry_seconds(1); 317 fake_hardware_.SetIsOfficialBuild(false); 318 return ret; 319 } 320 321 // Necessary to unhide the definition in the base class. 322 using AnyHttpFetcherTest::NewSmallFetcher; 323 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override { 324 return NewLargeFetcher(proxy_resolver); 325 } 326 327 bool IsMulti() const override { return true; } 328 }; 329 330 class FileFetcherTest : public AnyHttpFetcherTest { 331 public: 332 // Necessary to unhide the definition in the base class. 333 using AnyHttpFetcherTest::NewLargeFetcher; 334 HttpFetcher* NewLargeFetcher(ProxyResolver* /* proxy_resolver */) override { 335 return new FileFetcher(); 336 } 337 338 // Necessary to unhide the definition in the base class. 339 using AnyHttpFetcherTest::NewSmallFetcher; 340 HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override { 341 return NewLargeFetcher(proxy_resolver); 342 } 343 344 string BigUrl(in_port_t port) const override { 345 return "file://" + temp_file_.path(); 346 } 347 string SmallUrl(in_port_t port) const override { 348 test_utils::WriteFileString(temp_file_.path(), "small contents"); 349 return "file://" + temp_file_.path(); 350 } 351 string ErrorUrl(in_port_t port) const override { 352 return "file:///path/to/non-existing-file"; 353 } 354 355 bool IsMock() const override { return false; } 356 bool IsMulti() const override { return false; } 357 bool IsHttpSupported() const override { return false; } 358 359 void IgnoreServerAborting(HttpServer* server) const override {} 360 361 HttpServer* CreateServer() override { return new NullHttpServer; } 362 363 private: 364 test_utils::ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"}; 365 }; 366 367 // 368 // Infrastructure for type tests of HTTP fetcher. 369 // See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests 370 // 371 372 // Fixture class template. We use an explicit constraint to guarantee that it 373 // can only be instantiated with an AnyHttpFetcherTest type, see: 374 // http://www2.research.att.com/~bs/bs_faq2.html#constraints 375 template <typename T> 376 class HttpFetcherTest : public ::testing::Test { 377 public: 378 base::MessageLoopForIO base_loop_; 379 brillo::BaseMessageLoop loop_{&base_loop_}; 380 381 T test_; 382 383 protected: 384 HttpFetcherTest() { 385 loop_.SetAsCurrent(); 386 } 387 388 void TearDown() override { 389 EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1)); 390 } 391 392 private: 393 static void TypeConstraint(T* a) { 394 AnyHttpFetcherTest *b = a; 395 if (b == 0) // Silence compiler warning of unused variable. 396 *b = a; 397 } 398 }; 399 400 // Test case types list. 401 typedef ::testing::Types<LibcurlHttpFetcherTest, 402 MockHttpFetcherTest, 403 MultiRangeHttpFetcherTest, 404 FileFetcherTest> 405 HttpFetcherTestTypes; 406 TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes); 407 408 409 namespace { 410 class HttpFetcherTestDelegate : public HttpFetcherDelegate { 411 public: 412 HttpFetcherTestDelegate() = default; 413 414 void ReceivedBytes(HttpFetcher* /* fetcher */, 415 const void* bytes, 416 size_t length) override { 417 data.append(reinterpret_cast<const char*>(bytes), length); 418 // Update counters 419 times_received_bytes_called_++; 420 } 421 422 void TransferComplete(HttpFetcher* fetcher, bool successful) override { 423 if (is_expect_error_) 424 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code()); 425 else 426 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code()); 427 MessageLoop::current()->BreakLoop(); 428 429 // Update counter 430 times_transfer_complete_called_++; 431 } 432 433 void TransferTerminated(HttpFetcher* fetcher) override { 434 times_transfer_terminated_called_++; 435 MessageLoop::current()->BreakLoop(); 436 } 437 438 // Are we expecting an error response? (default: no) 439 bool is_expect_error_{false}; 440 441 // Counters for callback invocations. 442 int times_transfer_complete_called_{0}; 443 int times_transfer_terminated_called_{0}; 444 int times_received_bytes_called_{0}; 445 446 // The received data bytes. 447 string data; 448 }; 449 450 451 void StartTransfer(HttpFetcher* http_fetcher, const string& url) { 452 http_fetcher->BeginTransfer(url); 453 } 454 } // namespace 455 456 TYPED_TEST(HttpFetcherTest, SimpleTest) { 457 HttpFetcherTestDelegate delegate; 458 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher()); 459 fetcher->set_delegate(&delegate); 460 461 unique_ptr<HttpServer> server(this->test_.CreateServer()); 462 ASSERT_TRUE(server->started_); 463 464 this->loop_.PostTask(FROM_HERE, base::Bind( 465 StartTransfer, 466 fetcher.get(), 467 this->test_.SmallUrl(server->GetPort()))); 468 this->loop_.Run(); 469 EXPECT_EQ(0, delegate.times_transfer_terminated_called_); 470 } 471 472 TYPED_TEST(HttpFetcherTest, SimpleBigTest) { 473 HttpFetcherTestDelegate delegate; 474 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher()); 475 fetcher->set_delegate(&delegate); 476 477 unique_ptr<HttpServer> server(this->test_.CreateServer()); 478 ASSERT_TRUE(server->started_); 479 480 this->loop_.PostTask(FROM_HERE, base::Bind( 481 StartTransfer, 482 fetcher.get(), 483 this->test_.BigUrl(server->GetPort()))); 484 this->loop_.Run(); 485 EXPECT_EQ(0, delegate.times_transfer_terminated_called_); 486 } 487 488 // Issue #9648: when server returns an error HTTP response, the fetcher needs to 489 // terminate transfer prematurely, rather than try to process the error payload. 490 TYPED_TEST(HttpFetcherTest, ErrorTest) { 491 if (this->test_.IsMock() || this->test_.IsMulti()) 492 return; 493 HttpFetcherTestDelegate delegate; 494 495 // Delegate should expect an error response. 496 delegate.is_expect_error_ = true; 497 498 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher()); 499 fetcher->set_delegate(&delegate); 500 501 unique_ptr<HttpServer> server(this->test_.CreateServer()); 502 ASSERT_TRUE(server->started_); 503 504 this->loop_.PostTask(FROM_HERE, base::Bind( 505 StartTransfer, 506 fetcher.get(), 507 this->test_.ErrorUrl(server->GetPort()))); 508 this->loop_.Run(); 509 510 // Make sure that no bytes were received. 511 EXPECT_EQ(0, delegate.times_received_bytes_called_); 512 EXPECT_EQ(0U, fetcher->GetBytesDownloaded()); 513 514 // Make sure that transfer completion was signaled once, and no termination 515 // was signaled. 516 EXPECT_EQ(1, delegate.times_transfer_complete_called_); 517 EXPECT_EQ(0, delegate.times_transfer_terminated_called_); 518 } 519 520 TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) { 521 if (this->test_.IsMock() || !this->test_.IsHttpSupported()) 522 return; 523 524 HttpFetcherTestDelegate delegate; 525 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher()); 526 fetcher->set_delegate(&delegate); 527 fetcher->SetHeader("User-Agent", "MyTest"); 528 fetcher->SetHeader("user-agent", "Override that header"); 529 fetcher->SetHeader("Authorization", "Basic user:passwd"); 530 531 // Invalid headers. 532 fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored"); 533 fetcher->SetHeader("X-Bar: ", "I do not know how to parse"); 534 535 // Hide Accept header normally added by default. 536 fetcher->SetHeader("Accept", ""); 537 538 PythonHttpServer server; 539 int port = server.GetPort(); 540 ASSERT_TRUE(server.started_); 541 542 this->loop_.PostTask( 543 FROM_HERE, 544 base::Bind(StartTransfer, 545 fetcher.get(), 546 LocalServerUrlForPath(port, "/echo-headers"))); 547 this->loop_.Run(); 548 549 EXPECT_NE(string::npos, 550 delegate.data.find("user-agent: Override that header\r\n")); 551 EXPECT_NE(string::npos, 552 delegate.data.find("Authorization: Basic user:passwd\r\n")); 553 554 EXPECT_EQ(string::npos, delegate.data.find("\nAccept:")); 555 EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid")); 556 EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not")); 557 } 558 559 namespace { 560 class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate { 561 public: 562 void ReceivedBytes(HttpFetcher* fetcher, 563 const void* /* bytes */, size_t /* length */) override { 564 CHECK(!paused_); 565 paused_ = true; 566 fetcher->Pause(); 567 } 568 void TransferComplete(HttpFetcher* fetcher, bool successful) override { 569 MessageLoop::current()->BreakLoop(); 570 } 571 void TransferTerminated(HttpFetcher* fetcher) override { 572 ADD_FAILURE(); 573 } 574 void Unpause() { 575 CHECK(paused_); 576 paused_ = false; 577 fetcher_->Unpause(); 578 } 579 bool paused_; 580 HttpFetcher* fetcher_; 581 }; 582 583 void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate, 584 MessageLoop::TaskId* my_id) { 585 if (delegate->paused_) 586 delegate->Unpause(); 587 // Update the task id with the new scheduled callback. 588 *my_id = MessageLoop::current()->PostDelayedTask( 589 FROM_HERE, 590 base::Bind(&UnpausingTimeoutCallback, delegate, my_id), 591 base::TimeDelta::FromMilliseconds(200)); 592 } 593 } // namespace 594 595 TYPED_TEST(HttpFetcherTest, PauseTest) { 596 PausingHttpFetcherTestDelegate delegate; 597 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher()); 598 delegate.paused_ = false; 599 delegate.fetcher_ = fetcher.get(); 600 fetcher->set_delegate(&delegate); 601 602 unique_ptr<HttpServer> server(this->test_.CreateServer()); 603 ASSERT_TRUE(server->started_); 604 605 MessageLoop::TaskId callback_id; 606 callback_id = this->loop_.PostDelayedTask( 607 FROM_HERE, 608 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id), 609 base::TimeDelta::FromMilliseconds(200)); 610 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort())); 611 612 this->loop_.Run(); 613 EXPECT_TRUE(this->loop_.CancelTask(callback_id)); 614 } 615 616 // This test will pause the fetcher while the download is not yet started 617 // because it is waiting for the proxy to be resolved. 618 TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) { 619 if (this->test_.IsMock() || !this->test_.IsHttpSupported()) 620 return; 621 MockProxyResolver mock_resolver; 622 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver)); 623 624 // Saved arguments from the proxy call. 625 ProxiesResolvedFn proxy_callback; 626 EXPECT_CALL(mock_resolver, GetProxiesForUrl("http://fake_url", _)) 627 .WillOnce(DoAll(SaveArg<1>(&proxy_callback), Return(true))); 628 fetcher->BeginTransfer("http://fake_url"); 629 testing::Mock::VerifyAndClearExpectations(&mock_resolver); 630 631 // Pausing and unpausing while resolving the proxy should not affect anything. 632 fetcher->Pause(); 633 fetcher->Unpause(); 634 fetcher->Pause(); 635 // Proxy resolver comes back after we paused the fetcher. 636 ASSERT_FALSE(proxy_callback.is_null()); 637 proxy_callback.Run({1, kNoProxy}); 638 } 639 640 namespace { 641 class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate { 642 public: 643 void ReceivedBytes(HttpFetcher* fetcher, 644 const void* bytes, size_t length) override {} 645 void TransferComplete(HttpFetcher* fetcher, bool successful) override { 646 ADD_FAILURE(); // We should never get here 647 MessageLoop::current()->BreakLoop(); 648 } 649 void TransferTerminated(HttpFetcher* fetcher) override { 650 EXPECT_EQ(fetcher, fetcher_.get()); 651 EXPECT_FALSE(once_); 652 EXPECT_TRUE(callback_once_); 653 callback_once_ = false; 654 // The fetcher could have a callback scheduled on the ProxyResolver that 655 // can fire after this callback. We wait until the end of the test to 656 // delete the fetcher. 657 } 658 void TerminateTransfer() { 659 CHECK(once_); 660 once_ = false; 661 fetcher_->TerminateTransfer(); 662 } 663 void EndLoop() { 664 MessageLoop::current()->BreakLoop(); 665 } 666 bool once_; 667 bool callback_once_; 668 unique_ptr<HttpFetcher> fetcher_; 669 }; 670 671 void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate, 672 MessageLoop::TaskId* my_id) { 673 if (delegate->once_) { 674 delegate->TerminateTransfer(); 675 *my_id = MessageLoop::current()->PostTask( 676 FROM_HERE, 677 base::Bind(AbortingTimeoutCallback, delegate, my_id)); 678 } else { 679 delegate->EndLoop(); 680 *my_id = MessageLoop::kTaskIdNull; 681 } 682 } 683 } // namespace 684 685 TYPED_TEST(HttpFetcherTest, AbortTest) { 686 AbortingHttpFetcherTestDelegate delegate; 687 delegate.fetcher_.reset(this->test_.NewLargeFetcher()); 688 delegate.once_ = true; 689 delegate.callback_once_ = true; 690 delegate.fetcher_->set_delegate(&delegate); 691 692 unique_ptr<HttpServer> server(this->test_.CreateServer()); 693 this->test_.IgnoreServerAborting(server.get()); 694 ASSERT_TRUE(server->started_); 695 696 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull; 697 698 task_id = this->loop_.PostTask( 699 FROM_HERE, 700 base::Bind(AbortingTimeoutCallback, &delegate, &task_id)); 701 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort())); 702 703 this->loop_.Run(); 704 CHECK(!delegate.once_); 705 CHECK(!delegate.callback_once_); 706 this->loop_.CancelTask(task_id); 707 } 708 709 TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) { 710 if (this->test_.IsMock() || !this->test_.IsHttpSupported()) 711 return; 712 MockProxyResolver mock_resolver; 713 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher(&mock_resolver)); 714 715 HttpFetcherTestDelegate delegate; 716 fetcher->set_delegate(&delegate); 717 718 EXPECT_CALL(mock_resolver, GetProxiesForUrl(_, _)).WillOnce(Return(123)); 719 fetcher->BeginTransfer("http://fake_url"); 720 // Run the message loop until idle. This must call the MockProxyResolver with 721 // the request. 722 while (this->loop_.RunOnce(false)) { 723 } 724 testing::Mock::VerifyAndClearExpectations(&mock_resolver); 725 726 EXPECT_CALL(mock_resolver, CancelProxyRequest(123)).WillOnce(Return(true)); 727 728 // Terminate the transfer right before the proxy resolution response. 729 fetcher->TerminateTransfer(); 730 EXPECT_EQ(0, delegate.times_received_bytes_called_); 731 EXPECT_EQ(0, delegate.times_transfer_complete_called_); 732 EXPECT_EQ(1, delegate.times_transfer_terminated_called_); 733 } 734 735 namespace { 736 class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate { 737 public: 738 void ReceivedBytes(HttpFetcher* fetcher, 739 const void* bytes, size_t length) override { 740 data.append(reinterpret_cast<const char*>(bytes), length); 741 } 742 void TransferComplete(HttpFetcher* fetcher, bool successful) override { 743 EXPECT_TRUE(successful); 744 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code()); 745 MessageLoop::current()->BreakLoop(); 746 } 747 void TransferTerminated(HttpFetcher* fetcher) override { 748 ADD_FAILURE(); 749 } 750 string data; 751 }; 752 } // namespace 753 754 TYPED_TEST(HttpFetcherTest, FlakyTest) { 755 if (this->test_.IsMock() || !this->test_.IsHttpSupported()) 756 return; 757 { 758 FlakyHttpFetcherTestDelegate delegate; 759 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher()); 760 fetcher->set_delegate(&delegate); 761 762 unique_ptr<HttpServer> server(this->test_.CreateServer()); 763 ASSERT_TRUE(server->started_); 764 765 this->loop_.PostTask(FROM_HERE, base::Bind( 766 &StartTransfer, 767 fetcher.get(), 768 LocalServerUrlForPath(server->GetPort(), 769 base::StringPrintf("/flaky/%d/%d/%d/%d", 770 kBigLength, 771 kFlakyTruncateLength, 772 kFlakySleepEvery, 773 kFlakySleepSecs)))); 774 this->loop_.Run(); 775 776 // verify the data we get back 777 ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size())); 778 for (int i = 0; i < kBigLength; i += 10) { 779 // Assert so that we don't flood the screen w/ EXPECT errors on failure. 780 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij"); 781 } 782 } 783 } 784 785 namespace { 786 // This delegate kills the server attached to it after receiving any bytes. 787 // This can be used for testing what happens when you try to fetch data and 788 // the server dies. 789 class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate { 790 public: 791 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server) 792 : server_(server) {} 793 794 ~FailureHttpFetcherTestDelegate() override { 795 if (server_) { 796 LOG(INFO) << "Stopping server in destructor"; 797 server_.reset(); 798 LOG(INFO) << "server stopped"; 799 } 800 } 801 802 void ReceivedBytes(HttpFetcher* fetcher, 803 const void* bytes, size_t length) override { 804 if (server_) { 805 LOG(INFO) << "Stopping server in ReceivedBytes"; 806 server_.reset(); 807 LOG(INFO) << "server stopped"; 808 } 809 } 810 void TransferComplete(HttpFetcher* fetcher, bool successful) override { 811 EXPECT_FALSE(successful); 812 EXPECT_EQ(0, fetcher->http_response_code()); 813 times_transfer_complete_called_++; 814 MessageLoop::current()->BreakLoop(); 815 } 816 void TransferTerminated(HttpFetcher* fetcher) override { 817 times_transfer_terminated_called_++; 818 MessageLoop::current()->BreakLoop(); 819 } 820 unique_ptr<PythonHttpServer> server_; 821 int times_transfer_terminated_called_{0}; 822 int times_transfer_complete_called_{0}; 823 }; 824 } // namespace 825 826 827 TYPED_TEST(HttpFetcherTest, FailureTest) { 828 // This test ensures that a fetcher responds correctly when a server isn't 829 // available at all. 830 if (this->test_.IsMock()) 831 return; 832 FailureHttpFetcherTestDelegate delegate(nullptr); 833 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher()); 834 fetcher->set_delegate(&delegate); 835 836 this->loop_.PostTask( 837 FROM_HERE, 838 base::Bind( 839 StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999")); 840 this->loop_.Run(); 841 EXPECT_EQ(1, delegate.times_transfer_complete_called_); 842 EXPECT_EQ(0, delegate.times_transfer_terminated_called_); 843 844 // Exiting and testing happens in the delegate 845 } 846 847 TYPED_TEST(HttpFetcherTest, NoResponseTest) { 848 // This test starts a new http server but the server doesn't respond and just 849 // closes the connection. 850 if (this->test_.IsMock()) 851 return; 852 853 PythonHttpServer* server = new PythonHttpServer(); 854 int port = server->GetPort(); 855 ASSERT_TRUE(server->started_); 856 857 // Handles destruction and claims ownership. 858 FailureHttpFetcherTestDelegate delegate(server); 859 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher()); 860 fetcher->set_delegate(&delegate); 861 // The server will not reply at all, so we can limit the execution time of the 862 // test by reducing the low-speed timeout to something small. The test will 863 // finish once the TimeoutCallback() triggers (every second) and the timeout 864 // expired. 865 fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1); 866 867 this->loop_.PostTask(FROM_HERE, base::Bind( 868 StartTransfer, 869 fetcher.get(), 870 LocalServerUrlForPath(port, "/hang"))); 871 this->loop_.Run(); 872 EXPECT_EQ(1, delegate.times_transfer_complete_called_); 873 EXPECT_EQ(0, delegate.times_transfer_terminated_called_); 874 875 // Check that no other callback runs in the next two seconds. That would 876 // indicate a leaked callback. 877 bool timeout = false; 878 auto callback = base::Bind([](bool* timeout) { *timeout = true; }, 879 base::Unretained(&timeout)); 880 this->loop_.PostDelayedTask(FROM_HERE, callback, 881 base::TimeDelta::FromSeconds(2)); 882 EXPECT_TRUE(this->loop_.RunOnce(true)); 883 EXPECT_TRUE(timeout); 884 } 885 886 TYPED_TEST(HttpFetcherTest, ServerDiesTest) { 887 // This test starts a new http server and kills it after receiving its first 888 // set of bytes. It test whether or not our fetcher eventually gives up on 889 // retries and aborts correctly. 890 if (this->test_.IsMock()) 891 return; 892 PythonHttpServer* server = new PythonHttpServer(); 893 int port = server->GetPort(); 894 ASSERT_TRUE(server->started_); 895 896 // Handles destruction and claims ownership. 897 FailureHttpFetcherTestDelegate delegate(server); 898 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher()); 899 fetcher->set_delegate(&delegate); 900 901 this->loop_.PostTask( 902 FROM_HERE, 903 base::Bind(StartTransfer, 904 fetcher.get(), 905 LocalServerUrlForPath(port, 906 base::StringPrintf("/flaky/%d/%d/%d/%d", 907 kBigLength, 908 kFlakyTruncateLength, 909 kFlakySleepEvery, 910 kFlakySleepSecs)))); 911 this->loop_.Run(); 912 EXPECT_EQ(1, delegate.times_transfer_complete_called_); 913 EXPECT_EQ(0, delegate.times_transfer_terminated_called_); 914 915 // Exiting and testing happens in the delegate 916 } 917 918 // Test that we can cancel a transfer while it is still trying to connect to the 919 // server. This test kills the server after a few bytes are received. 920 TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) { 921 if (this->test_.IsMock() || !this->test_.IsHttpSupported()) 922 return; 923 924 PythonHttpServer* server = new PythonHttpServer(); 925 int port = server->GetPort(); 926 ASSERT_TRUE(server->started_); 927 928 // Handles destruction and claims ownership. 929 FailureHttpFetcherTestDelegate delegate(server); 930 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher()); 931 fetcher->set_delegate(&delegate); 932 933 this->loop_.PostTask( 934 FROM_HERE, 935 base::Bind(StartTransfer, 936 fetcher.get(), 937 LocalServerUrlForPath(port, 938 base::StringPrintf("/flaky/%d/%d/%d/%d", 939 kBigLength, 940 kFlakyTruncateLength, 941 kFlakySleepEvery, 942 kFlakySleepSecs)))); 943 // Terminating the transfer after 3 seconds gives it a chance to contact the 944 // server and enter the retry loop. 945 this->loop_.PostDelayedTask(FROM_HERE, 946 base::Bind(&HttpFetcher::TerminateTransfer, 947 base::Unretained(fetcher.get())), 948 base::TimeDelta::FromSeconds(3)); 949 950 // Exiting and testing happens in the delegate. 951 this->loop_.Run(); 952 EXPECT_EQ(0, delegate.times_transfer_complete_called_); 953 EXPECT_EQ(1, delegate.times_transfer_terminated_called_); 954 955 // Check that no other callback runs in the next two seconds. That would 956 // indicate a leaked callback. 957 bool timeout = false; 958 auto callback = base::Bind([](bool* timeout) { *timeout = true; }, 959 base::Unretained(&timeout)); 960 this->loop_.PostDelayedTask( 961 FROM_HERE, callback, base::TimeDelta::FromSeconds(2)); 962 EXPECT_TRUE(this->loop_.RunOnce(true)); 963 EXPECT_TRUE(timeout); 964 } 965 966 namespace { 967 const HttpResponseCode kRedirectCodes[] = { 968 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther, 969 kHttpResponseTempRedirect 970 }; 971 972 class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate { 973 public: 974 explicit RedirectHttpFetcherTestDelegate(bool expected_successful) 975 : expected_successful_(expected_successful) {} 976 void ReceivedBytes(HttpFetcher* fetcher, 977 const void* bytes, size_t length) override { 978 data.append(reinterpret_cast<const char*>(bytes), length); 979 } 980 void TransferComplete(HttpFetcher* fetcher, bool successful) override { 981 EXPECT_EQ(expected_successful_, successful); 982 if (expected_successful_) { 983 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code()); 984 } else { 985 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently); 986 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect); 987 } 988 MessageLoop::current()->BreakLoop(); 989 } 990 void TransferTerminated(HttpFetcher* fetcher) override { 991 ADD_FAILURE(); 992 } 993 bool expected_successful_; 994 string data; 995 }; 996 997 // RedirectTest takes ownership of |http_fetcher|. 998 void RedirectTest(const HttpServer* server, 999 bool expected_successful, 1000 const string& url, 1001 HttpFetcher* http_fetcher) { 1002 RedirectHttpFetcherTestDelegate delegate(expected_successful); 1003 unique_ptr<HttpFetcher> fetcher(http_fetcher); 1004 fetcher->set_delegate(&delegate); 1005 1006 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 1007 StartTransfer, 1008 fetcher.get(), 1009 LocalServerUrlForPath(server->GetPort(), url))); 1010 MessageLoop::current()->Run(); 1011 if (expected_successful) { 1012 // verify the data we get back 1013 ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size()); 1014 for (int i = 0; i < kMediumLength; i += 10) { 1015 // Assert so that we don't flood the screen w/ EXPECT errors on failure. 1016 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij"); 1017 } 1018 } 1019 } 1020 } // namespace 1021 1022 TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) { 1023 if (this->test_.IsMock() || !this->test_.IsHttpSupported()) 1024 return; 1025 1026 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1027 ASSERT_TRUE(server->started_); 1028 1029 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) { 1030 const string url = base::StringPrintf("/redirect/%d/download/%d", 1031 kRedirectCodes[c], 1032 kMediumLength); 1033 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher()); 1034 } 1035 } 1036 1037 TYPED_TEST(HttpFetcherTest, MaxRedirectTest) { 1038 if (this->test_.IsMock() || !this->test_.IsHttpSupported()) 1039 return; 1040 1041 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1042 ASSERT_TRUE(server->started_); 1043 1044 string url; 1045 for (int r = 0; r < kDownloadMaxRedirects; r++) { 1046 url += base::StringPrintf("/redirect/%d", 1047 kRedirectCodes[r % arraysize(kRedirectCodes)]); 1048 } 1049 url += base::StringPrintf("/download/%d", kMediumLength); 1050 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher()); 1051 } 1052 1053 TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) { 1054 if (this->test_.IsMock() || !this->test_.IsHttpSupported()) 1055 return; 1056 1057 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1058 ASSERT_TRUE(server->started_); 1059 1060 string url; 1061 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) { 1062 url += base::StringPrintf("/redirect/%d", 1063 kRedirectCodes[r % arraysize(kRedirectCodes)]); 1064 } 1065 url += base::StringPrintf("/download/%d", kMediumLength); 1066 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher()); 1067 } 1068 1069 namespace { 1070 class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate { 1071 public: 1072 explicit MultiHttpFetcherTestDelegate(int expected_response_code) 1073 : expected_response_code_(expected_response_code) {} 1074 1075 void ReceivedBytes(HttpFetcher* fetcher, 1076 const void* bytes, size_t length) override { 1077 EXPECT_EQ(fetcher, fetcher_.get()); 1078 data.append(reinterpret_cast<const char*>(bytes), length); 1079 } 1080 1081 void TransferComplete(HttpFetcher* fetcher, bool successful) override { 1082 EXPECT_EQ(fetcher, fetcher_.get()); 1083 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful); 1084 if (expected_response_code_ != 0) 1085 EXPECT_EQ(expected_response_code_, fetcher->http_response_code()); 1086 // Destroy the fetcher (because we're allowed to). 1087 fetcher_.reset(nullptr); 1088 MessageLoop::current()->BreakLoop(); 1089 } 1090 1091 void TransferTerminated(HttpFetcher* fetcher) override { 1092 ADD_FAILURE(); 1093 } 1094 1095 unique_ptr<HttpFetcher> fetcher_; 1096 int expected_response_code_; 1097 string data; 1098 }; 1099 1100 void MultiTest(HttpFetcher* fetcher_in, 1101 FakeHardware* fake_hardware, 1102 const string& url, 1103 const vector<pair<off_t, off_t>>& ranges, 1104 const string& expected_prefix, 1105 size_t expected_size, 1106 HttpResponseCode expected_response_code) { 1107 MultiHttpFetcherTestDelegate delegate(expected_response_code); 1108 delegate.fetcher_.reset(fetcher_in); 1109 1110 MultiRangeHttpFetcher* multi_fetcher = 1111 static_cast<MultiRangeHttpFetcher*>(fetcher_in); 1112 ASSERT_TRUE(multi_fetcher); 1113 multi_fetcher->ClearRanges(); 1114 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(), 1115 e = ranges.end(); it != e; ++it) { 1116 string tmp_str = base::StringPrintf("%jd+", it->first); 1117 if (it->second > 0) { 1118 base::StringAppendF(&tmp_str, "%jd", it->second); 1119 multi_fetcher->AddRange(it->first, it->second); 1120 } else { 1121 base::StringAppendF(&tmp_str, "?"); 1122 multi_fetcher->AddRange(it->first); 1123 } 1124 LOG(INFO) << "added range: " << tmp_str; 1125 } 1126 fake_hardware->SetIsOfficialBuild(false); 1127 multi_fetcher->set_delegate(&delegate); 1128 1129 MessageLoop::current()->PostTask( 1130 FROM_HERE, 1131 base::Bind(StartTransfer, multi_fetcher, url)); 1132 MessageLoop::current()->Run(); 1133 1134 EXPECT_EQ(expected_size, delegate.data.size()); 1135 EXPECT_EQ(expected_prefix, 1136 string(delegate.data.data(), expected_prefix.size())); 1137 } 1138 } // namespace 1139 1140 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) { 1141 if (!this->test_.IsMulti()) 1142 return; 1143 1144 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1145 ASSERT_TRUE(server->started_); 1146 1147 vector<pair<off_t, off_t>> ranges; 1148 ranges.push_back(make_pair(0, 25)); 1149 ranges.push_back(make_pair(99, 0)); 1150 MultiTest(this->test_.NewLargeFetcher(), 1151 this->test_.fake_hardware(), 1152 this->test_.BigUrl(server->GetPort()), 1153 ranges, 1154 "abcdefghijabcdefghijabcdejabcdefghijabcdef", 1155 kBigLength - (99 - 25), 1156 kHttpResponsePartialContent); 1157 } 1158 1159 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) { 1160 if (!this->test_.IsMulti()) 1161 return; 1162 1163 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1164 ASSERT_TRUE(server->started_); 1165 1166 vector<pair<off_t, off_t>> ranges; 1167 ranges.push_back(make_pair(0, 24)); 1168 MultiTest(this->test_.NewLargeFetcher(), 1169 this->test_.fake_hardware(), 1170 this->test_.BigUrl(server->GetPort()), 1171 ranges, 1172 "abcdefghijabcdefghijabcd", 1173 24, 1174 kHttpResponsePartialContent); 1175 } 1176 1177 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) { 1178 if (!this->test_.IsMulti()) 1179 return; 1180 1181 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1182 ASSERT_TRUE(server->started_); 1183 1184 vector<pair<off_t, off_t>> ranges; 1185 ranges.push_back(make_pair(kBigLength - 2, 0)); 1186 ranges.push_back(make_pair(kBigLength - 3, 0)); 1187 MultiTest(this->test_.NewLargeFetcher(), 1188 this->test_.fake_hardware(), 1189 this->test_.BigUrl(server->GetPort()), 1190 ranges, 1191 "ijhij", 1192 5, 1193 kHttpResponsePartialContent); 1194 } 1195 1196 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) { 1197 if (!this->test_.IsMulti()) 1198 return; 1199 1200 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1201 ASSERT_TRUE(server->started_); 1202 1203 vector<pair<off_t, off_t>> ranges; 1204 ranges.push_back(make_pair(kBigLength - 2, 4)); 1205 for (int i = 0; i < 2; ++i) { 1206 LOG(INFO) << "i = " << i; 1207 MultiTest(this->test_.NewLargeFetcher(), 1208 this->test_.fake_hardware(), 1209 this->test_.BigUrl(server->GetPort()), 1210 ranges, 1211 "ij", 1212 2, 1213 kHttpResponseUndefined); 1214 ranges.push_back(make_pair(0, 5)); 1215 } 1216 } 1217 1218 // Issue #18143: when a fetch of a secondary chunk out of a chain, then it 1219 // should retry with other proxies listed before giving up. 1220 // 1221 // (1) successful recovery: The offset fetch will fail twice but succeed with 1222 // the third proxy. 1223 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) { 1224 if (!this->test_.IsMulti()) 1225 return; 1226 1227 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1228 ASSERT_TRUE(server->started_); 1229 1230 vector<pair<off_t, off_t>> ranges; 1231 ranges.push_back(make_pair(0, 25)); 1232 ranges.push_back(make_pair(99, 0)); 1233 MultiTest(this->test_.NewLargeFetcher(3), 1234 this->test_.fake_hardware(), 1235 LocalServerUrlForPath(server->GetPort(), 1236 base::StringPrintf("/error-if-offset/%d/2", 1237 kBigLength)), 1238 ranges, 1239 "abcdefghijabcdefghijabcdejabcdefghijabcdef", 1240 kBigLength - (99 - 25), 1241 kHttpResponsePartialContent); 1242 } 1243 1244 // (2) unsuccessful recovery: The offset fetch will fail repeatedly. The 1245 // fetcher will signal a (failed) completed transfer to the delegate. 1246 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) { 1247 if (!this->test_.IsMulti()) 1248 return; 1249 1250 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1251 ASSERT_TRUE(server->started_); 1252 1253 vector<pair<off_t, off_t>> ranges; 1254 ranges.push_back(make_pair(0, 25)); 1255 ranges.push_back(make_pair(99, 0)); 1256 MultiTest(this->test_.NewLargeFetcher(2), 1257 this->test_.fake_hardware(), 1258 LocalServerUrlForPath(server->GetPort(), 1259 base::StringPrintf("/error-if-offset/%d/3", 1260 kBigLength)), 1261 ranges, 1262 "abcdefghijabcdefghijabcde", // only received the first chunk 1263 25, 1264 kHttpResponseUndefined); 1265 } 1266 1267 namespace { 1268 // This HttpFetcherDelegate calls TerminateTransfer at a configurable point. 1269 class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate { 1270 public: 1271 explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes) 1272 : terminate_trigger_bytes_(terminate_trigger_bytes) {} 1273 1274 void ReceivedBytes(HttpFetcher* fetcher, 1275 const void* bytes, 1276 size_t length) override { 1277 LOG(INFO) << "ReceivedBytes, " << length << " bytes."; 1278 EXPECT_EQ(fetcher, fetcher_.get()); 1279 if (bytes_downloaded_ < terminate_trigger_bytes_ && 1280 bytes_downloaded_ + length >= terminate_trigger_bytes_) { 1281 MessageLoop::current()->PostTask( 1282 FROM_HERE, 1283 base::Bind(&HttpFetcher::TerminateTransfer, 1284 base::Unretained(fetcher_.get()))); 1285 } 1286 bytes_downloaded_ += length; 1287 } 1288 1289 void TransferComplete(HttpFetcher* fetcher, bool successful) override { 1290 ADD_FAILURE() << "TransferComplete called but expected a failure"; 1291 // Destroy the fetcher (because we're allowed to). 1292 fetcher_.reset(nullptr); 1293 MessageLoop::current()->BreakLoop(); 1294 } 1295 1296 void TransferTerminated(HttpFetcher* fetcher) override { 1297 // Destroy the fetcher (because we're allowed to). 1298 fetcher_.reset(nullptr); 1299 MessageLoop::current()->BreakLoop(); 1300 } 1301 1302 unique_ptr<HttpFetcher> fetcher_; 1303 size_t bytes_downloaded_{0}; 1304 size_t terminate_trigger_bytes_; 1305 }; 1306 } // namespace 1307 1308 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) { 1309 if (!this->test_.IsMulti()) 1310 return; 1311 const size_t kRangeTrigger = 1000; 1312 MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger); 1313 1314 unique_ptr<HttpServer> server(this->test_.CreateServer()); 1315 ASSERT_TRUE(server->started_); 1316 1317 MultiRangeHttpFetcher* multi_fetcher = 1318 static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher()); 1319 ASSERT_TRUE(multi_fetcher); 1320 // Transfer ownership of the fetcher to the delegate. 1321 delegate.fetcher_.reset(multi_fetcher); 1322 multi_fetcher->set_delegate(&delegate); 1323 1324 multi_fetcher->ClearRanges(); 1325 multi_fetcher->AddRange(45, kRangeTrigger); 1326 multi_fetcher->AddRange(2000, 100); 1327 1328 this->test_.fake_hardware()->SetIsOfficialBuild(false); 1329 1330 StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort())); 1331 MessageLoop::current()->Run(); 1332 1333 // Check that the delegate made it to the trigger point. 1334 EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_); 1335 } 1336 1337 namespace { 1338 class BlockedTransferTestDelegate : public HttpFetcherDelegate { 1339 public: 1340 void ReceivedBytes(HttpFetcher* fetcher, 1341 const void* bytes, size_t length) override { 1342 ADD_FAILURE(); 1343 } 1344 void TransferComplete(HttpFetcher* fetcher, bool successful) override { 1345 EXPECT_FALSE(successful); 1346 MessageLoop::current()->BreakLoop(); 1347 } 1348 void TransferTerminated(HttpFetcher* fetcher) override { 1349 ADD_FAILURE(); 1350 } 1351 }; 1352 1353 void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test, 1354 bool is_official_build) { 1355 if (fetcher_test->IsMock() || fetcher_test->IsMulti()) 1356 return; 1357 1358 unique_ptr<HttpServer> server(fetcher_test->CreateServer()); 1359 ASSERT_TRUE(server->started_); 1360 1361 BlockedTransferTestDelegate delegate; 1362 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher()); 1363 LOG(INFO) << "is_official_build: " << is_official_build; 1364 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState. 1365 fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build); 1366 fetcher->set_delegate(&delegate); 1367 1368 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 1369 StartTransfer, 1370 fetcher.get(), 1371 LocalServerUrlForPath(server->GetPort(), 1372 fetcher_test->SmallUrl(server->GetPort())))); 1373 MessageLoop::current()->Run(); 1374 } 1375 } // namespace 1376 1377 TYPED_TEST(HttpFetcherTest, BlockedTransferTest) { 1378 BlockedTransferTestHelper(&this->test_, false); 1379 } 1380 1381 TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) { 1382 BlockedTransferTestHelper(&this->test_, true); 1383 } 1384 1385 } // namespace chromeos_update_engine 1386