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