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