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