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