Home | History | Annotate | Download | only in common
      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 
     55 using brillo::MessageLoop;
     56 using std::make_pair;
     57 using std::pair;
     58 using std::string;
     59 using std::unique_ptr;
     60 using std::vector;
     61 using testing::DoAll;
     62 using testing::Return;
     63 using testing::SaveArg;
     64 using testing::_;
     65 
     66 namespace {
     67 
     68 const int kBigLength           = 100000;
     69 const int kMediumLength        = 1000;
     70 const int kFlakyTruncateLength = 29000;
     71 const int kFlakySleepEvery     = 3;
     72 const int kFlakySleepSecs      = 10;
     73 
     74 }  // namespace
     75 
     76 namespace chromeos_update_engine {
     77 
     78 static const char *kUnusedUrl = "unused://unused";
     79 
     80 static 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 
     91 class 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 
    103 HttpServer::~HttpServer() {}
    104 
    105 
    106 class NullHttpServer : public HttpServer {
    107  public:
    108   NullHttpServer() {
    109     started_ = true;
    110   }
    111 };
    112 
    113 
    114 class 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 
    189 const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
    190 
    191 //
    192 // Class hierarchy for HTTP fetcher test wrappers.
    193 //
    194 
    195 class 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 
    236 class 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 
    261 class 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 
    306 class 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 
    331 class 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
    376 template <typename T>
    377 class 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.
    402 typedef ::testing::Types<LibcurlHttpFetcherTest,
    403                          MockHttpFetcherTest,
    404                          MultiRangeHttpFetcherTest,
    405                          FileFetcherTest>
    406     HttpFetcherTestTypes;
    407 TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
    408 
    409 
    410 namespace {
    411 class 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 
    452 void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
    453   http_fetcher->BeginTransfer(url);
    454 }
    455 }  // namespace
    456 
    457 TYPED_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 
    473 TYPED_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.
    491 TYPED_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 
    521 TYPED_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 
    560 namespace {
    561 class 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 
    584 void 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 
    596 TYPED_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.
    619 TYPED_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 
    641 namespace {
    642 class 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 
    672 void 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 
    686 TYPED_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 
    710 TYPED_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 
    736 namespace {
    737 class 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 
    755 TYPED_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 
    786 namespace {
    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.
    790 class 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 
    828 TYPED_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 
    848 TYPED_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 
    887 TYPED_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.
    921 TYPED_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 
    967 namespace {
    968 const HttpResponseCode kRedirectCodes[] = {
    969   kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
    970   kHttpResponseTempRedirect
    971 };
    972 
    973 class 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|.
    999 void 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 
   1023 TYPED_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 
   1038 TYPED_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 
   1054 TYPED_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 
   1070 namespace {
   1071 class 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 
   1101 void 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 
   1141 TYPED_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 
   1160 TYPED_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 
   1178 TYPED_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 
   1197 TYPED_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.
   1224 TYPED_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.
   1247 TYPED_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 
   1268 namespace {
   1269 // This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
   1270 class 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 
   1309 TYPED_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 
   1338 namespace {
   1339 class 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 
   1354 void 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 
   1378 TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
   1379   BlockedTransferTestHelper(&this->test_, false);
   1380 }
   1381 
   1382 TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
   1383   BlockedTransferTestHelper(&this->test_, true);
   1384 }
   1385 
   1386 }  // namespace chromeos_update_engine
   1387