//
// Copyright (C) 2012 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <unistd.h>

#include <algorithm>
#include <deque>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/location.h>
#include <base/logging.h>
#if BASE_VER < 780000  // Android
#include <base/message_loop/message_loop.h>
#endif  // BASE_VER < 780000
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#if BASE_VER >= 780000  // CrOS
#include <base/task/single_thread_task_executor.h>
#endif  // BASE_VER >= 780000
#include <base/time/time.h>
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/message_loops/message_loop.h>
#include <brillo/message_loops/message_loop_utils.h>
#ifdef __CHROMEOS__
#include <brillo/process/process.h>
#else
#include <brillo/process.h>
#endif  // __CHROMEOS__
#include <brillo/streams/file_stream.h>
#include <brillo/streams/stream.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "update_engine/common/fake_hardware.h"
#include "update_engine/common/file_fetcher.h"
#include "update_engine/common/http_common.h"
#include "update_engine/common/mock_http_fetcher.h"
#include "update_engine/common/multi_range_http_fetcher.h"
#include "update_engine/common/test_utils.h"
#include "update_engine/common/utils.h"
#include "update_engine/libcurl_http_fetcher.h"

using brillo::MessageLoop;
using std::make_pair;
using std::pair;
using std::string;
using std::unique_ptr;
using std::vector;
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SaveArg;

namespace {

const int kBigLength = 100000;
const int kMediumLength = 1000;
const int kFlakyTruncateLength = 29000;
const int kFlakySleepEvery = 3;
const int kFlakySleepSecs = 10;

}  // namespace

namespace chromeos_update_engine {

static const char* kUnusedUrl = "unused://unused";

static inline string LocalServerUrlForPath(in_port_t port, const string& path) {
  string port_str = (port ? base::StringPrintf(":%hu", port) : "");
  return base::StringPrintf(
      "http://127.0.0.1%s%s", port_str.c_str(), path.c_str());
}

//
// Class hierarchy for HTTP server implementations.
//

namespace {

class HttpServer {
 public:
  // This makes it an abstract class (dirty but works).
  virtual ~HttpServer() = 0;

  virtual in_port_t GetPort() const { return 0; }

  bool started_;
};

HttpServer::~HttpServer() {}

class NullHttpServer : public HttpServer {
 public:
  NullHttpServer() { started_ = true; }
};

class PythonHttpServer : public HttpServer {
 public:
  PythonHttpServer() : port_(0) {
    started_ = false;

    // Spawn the server process.
    unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
    http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
    http_server->RedirectUsingPipe(STDOUT_FILENO, false);

    if (!http_server->Start()) {
      ADD_FAILURE() << "failed to spawn http server process";
      return;
    }
    LOG(INFO) << "started http server with pid " << http_server->pid();

    // Wait for server to begin accepting connections, obtain its port.
    brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
        http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
    if (!stdout)
      return;

    vector<char> buf(128);
    string line;
    while (line.find('\n') == string::npos) {
      size_t read{};
      if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
        ADD_FAILURE() << "error reading http server stdout";
        return;
      }
      line.append(buf.data(), read);
      if (read == 0)
        break;
    }
    // Parse the port from the output line.
    const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
    if (line.size() < listening_msg_prefix_len) {
      ADD_FAILURE() << "server output too short";
      return;
    }

    EXPECT_EQ(kServerListeningMsgPrefix,
              line.substr(0, listening_msg_prefix_len));
    string port_str = line.substr(listening_msg_prefix_len);
    port_str.resize(port_str.find('\n'));
    EXPECT_TRUE(base::StringToUint(port_str, &port_));

    started_ = true;
    LOG(INFO) << "server running, listening on port " << port_;

    // Any failure before this point will SIGKILL the test server if started
    // when the |http_server| goes out of scope.
    http_server_ = std::move(http_server);
  }

  ~PythonHttpServer() {
    // If there's no process, do nothing.
    if (!http_server_)
      return;
    // Wait up to 10 seconds for the process to finish. Destroying the process
    // will kill it with a SIGKILL otherwise.
    http_server_->Kill(SIGTERM, 10);
  }

  in_port_t GetPort() const override { return port_; }

 private:
  static const char* kServerListeningMsgPrefix;

  unique_ptr<brillo::Process> http_server_;
  unsigned int port_;
};

const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";

//
// Class hierarchy for HTTP fetcher test wrappers.
//

class AnyHttpFetcherFactory {
 public:
  AnyHttpFetcherFactory() {}
  virtual ~AnyHttpFetcherFactory() {}

  virtual HttpFetcher* NewLargeFetcher() = 0;
  HttpFetcher* NewLargeFetcher(size_t num_proxies) {
    auto res = NewLargeFetcher();

    res->SetProxies(std::deque<std::string>(num_proxies, kNoProxy));
    return res;
  }

  virtual HttpFetcher* NewSmallFetcher() = 0;

  virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
  virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
  virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }

  virtual bool IsMock() const = 0;
  virtual bool IsMulti() const = 0;
  virtual bool IsHttpSupported() const = 0;
  virtual bool IsFileFetcher() const = 0;

  virtual void IgnoreServerAborting(HttpServer* server) const {}

  virtual HttpServer* CreateServer() = 0;

  FakeHardware* fake_hardware() { return &fake_hardware_; }

 protected:
  FakeHardware fake_hardware_;
};

class MockHttpFetcherFactory : public AnyHttpFetcherFactory {
 public:
  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewLargeFetcher;
  HttpFetcher* NewLargeFetcher() override {
    brillo::Blob big_data(1000000);
    return new MockHttpFetcher(big_data.data(), big_data.size());
  }

  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewSmallFetcher;
  HttpFetcher* NewSmallFetcher() override {
    return new MockHttpFetcher("x", 1);
  }

  bool IsMock() const override { return true; }
  bool IsMulti() const override { return false; }
  bool IsHttpSupported() const override { return true; }
  bool IsFileFetcher() const override { return false; }

  HttpServer* CreateServer() override { return new NullHttpServer; }
};

class LibcurlHttpFetcherFactory : public AnyHttpFetcherFactory {
 public:
  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewLargeFetcher;
  HttpFetcher* NewLargeFetcher() override {
    LibcurlHttpFetcher* ret = new LibcurlHttpFetcher(&fake_hardware_);
    // Speed up test execution.
    ret->set_idle_seconds(1);
    ret->set_retry_seconds(1);
    fake_hardware_.SetIsOfficialBuild(false);
    return ret;
  }

  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewSmallFetcher;

  HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }

  string BigUrl(in_port_t port) const override {
    return LocalServerUrlForPath(
        port, base::StringPrintf("/download/%d", kBigLength));
  }
  string SmallUrl(in_port_t port) const override {
    return LocalServerUrlForPath(port, "/foo");
  }
  string ErrorUrl(in_port_t port) const override {
    return LocalServerUrlForPath(port, "/error");
  }

  bool IsMock() const override { return false; }
  bool IsMulti() const override { return false; }
  bool IsHttpSupported() const override { return true; }
  bool IsFileFetcher() const override { return false; }

  void IgnoreServerAborting(HttpServer* server) const override {
    // Nothing to do.
  }

  HttpServer* CreateServer() override { return new PythonHttpServer; }
};

class MultiRangeHttpFetcherFactory : public LibcurlHttpFetcherFactory {
 public:
  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewLargeFetcher;
  HttpFetcher* NewLargeFetcher() override {
    MultiRangeHttpFetcher* ret =
        new MultiRangeHttpFetcher(new LibcurlHttpFetcher(&fake_hardware_));
    ret->ClearRanges();
    ret->AddRange(0);
    // Speed up test execution.
    ret->set_idle_seconds(1);
    ret->set_retry_seconds(1);
    fake_hardware_.SetIsOfficialBuild(false);
    return ret;
  }

  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewSmallFetcher;
  HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }

  bool IsMulti() const override { return true; }
};

class FileFetcherFactory : public AnyHttpFetcherFactory {
 public:
  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewLargeFetcher;
  HttpFetcher* NewLargeFetcher() override { return new FileFetcher(); }

  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewSmallFetcher;
  HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }

  string BigUrl(in_port_t port) const override {
    static string big_contents = []() {
      string buf;
      buf.reserve(kBigLength);
      constexpr const char* kBigUrlContent = "abcdefghij";
      for (size_t i = 0; i < kBigLength; i += strlen(kBigUrlContent)) {
        buf.append(kBigUrlContent,
                   std::min(kBigLength - i, strlen(kBigUrlContent)));
      }
      return buf;
    }();
    test_utils::WriteFileString(temp_file_.path(), big_contents);
    return "file://" + temp_file_.path();
  }
  string SmallUrl(in_port_t port) const override {
    test_utils::WriteFileString(temp_file_.path(), "small contents");
    return "file://" + temp_file_.path();
  }
  string ErrorUrl(in_port_t port) const override {
    return "file:///path/to/non-existing-file";
  }

  bool IsMock() const override { return false; }
  bool IsMulti() const override { return false; }
  bool IsHttpSupported() const override { return false; }
  bool IsFileFetcher() const override { return true; }

  void IgnoreServerAborting(HttpServer* server) const override {}

  HttpServer* CreateServer() override { return new NullHttpServer; }

 private:
  ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
};

class MultiRangeHttpFetcherOverFileFetcherFactory : public FileFetcherFactory {
 public:
  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewLargeFetcher;
  HttpFetcher* NewLargeFetcher() override {
    MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(new FileFetcher());
    ret->ClearRanges();
    // FileFetcher doesn't support range with unspecified length.
    ret->AddRange(0, 1);
    // Speed up test execution.
    ret->set_idle_seconds(1);
    ret->set_retry_seconds(1);
    fake_hardware_.SetIsOfficialBuild(false);
    return ret;
  }

  // Necessary to unhide the definition in the base class.
  using AnyHttpFetcherFactory::NewSmallFetcher;
  HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }

  bool IsMulti() const override { return true; }
};

//
// Infrastructure for type tests of HTTP fetcher.
// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
//

// Fixture class template. We use an explicit constraint to guarantee that it
// can only be instantiated with an AnyHttpFetcherTest type, see:
// http://www2.research.att.com/~bs/bs_faq2.html#constraints
template <typename T>
class HttpFetcherTest : public ::testing::Test {
 public:
#if BASE_VER < 780000  // Android
  base::MessageLoopForIO base_loop_;
  brillo::BaseMessageLoop loop_{&base_loop_};
#else   // Chrome OS
  base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
  brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
#endif  // BASE_VER < 780000

  T test_;

 protected:
  HttpFetcherTest() { loop_.SetAsCurrent(); }

  void TearDown() override {
    EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
  }

 private:
  static void TypeConstraint(T* a) {
    AnyHttpFetcherFactory* b = a;
    if (b == 0)  // Silence compiler warning of unused variable.
      *b = a;
  }
};

// Test case types list.
typedef ::testing::Types<LibcurlHttpFetcherFactory,
                         MockHttpFetcherFactory,
                         MultiRangeHttpFetcherFactory,
                         FileFetcherFactory,
                         MultiRangeHttpFetcherOverFileFetcherFactory>
    HttpFetcherTestTypes;
TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);

class HttpFetcherTestDelegate : public HttpFetcherDelegate {
 public:
  HttpFetcherTestDelegate() = default;

  bool ReceivedBytes(HttpFetcher* /* fetcher */,
                     const void* bytes,
                     size_t length) override {
    data.append(reinterpret_cast<const char*>(bytes), length);
    // Update counters
    times_received_bytes_called_++;
    return true;
  }

  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
    if (is_expect_error_)
      EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
    else
      EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
    MessageLoop::current()->BreakLoop();

    // Update counter
    times_transfer_complete_called_++;
  }

  void TransferTerminated(HttpFetcher* fetcher) override {
    times_transfer_terminated_called_++;
    MessageLoop::current()->BreakLoop();
  }

  // Are we expecting an error response? (default: no)
  bool is_expect_error_{false};

  // Counters for callback invocations.
  int times_transfer_complete_called_{0};
  int times_transfer_terminated_called_{0};
  int times_received_bytes_called_{0};

  // The received data bytes.
  string data;
};

void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
  http_fetcher->BeginTransfer(url);
}

TYPED_TEST(HttpFetcherTest, SimpleTest) {
  HttpFetcherTestDelegate delegate;
  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
  fetcher->set_delegate(&delegate);

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  this->loop_.PostTask(FROM_HERE,
                       base::Bind(StartTransfer,
                                  fetcher.get(),
                                  this->test_.SmallUrl(server->GetPort())));
  this->loop_.Run();
  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
}

TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
  HttpFetcherTestDelegate delegate;
  unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
  fetcher->set_delegate(&delegate);

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  this->loop_.PostTask(
      FROM_HERE,
      base::Bind(
          StartTransfer, fetcher.get(), this->test_.BigUrl(server->GetPort())));
  this->loop_.Run();
  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
}

// Issue #9648: when server returns an error HTTP response, the fetcher needs to
// terminate transfer prematurely, rather than try to process the error payload.
TYPED_TEST(HttpFetcherTest, ErrorTest) {
  if (this->test_.IsMock() || this->test_.IsMulti())
    return;
  HttpFetcherTestDelegate delegate;

  // Delegate should expect an error response.
  delegate.is_expect_error_ = true;

  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
  fetcher->set_delegate(&delegate);

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  this->loop_.PostTask(FROM_HERE,
                       base::Bind(StartTransfer,
                                  fetcher.get(),
                                  this->test_.ErrorUrl(server->GetPort())));
  this->loop_.Run();

  // Make sure that no bytes were received.
  EXPECT_EQ(0, delegate.times_received_bytes_called_);
  EXPECT_EQ(0U, fetcher->GetBytesDownloaded());

  // Make sure that transfer completion was signaled once, and no termination
  // was signaled.
  EXPECT_EQ(1, delegate.times_transfer_complete_called_);
  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
}

TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
    return;

  HttpFetcherTestDelegate delegate;
  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
  fetcher->set_delegate(&delegate);
  fetcher->SetHeader("User-Agent", "MyTest");
  fetcher->SetHeader("user-agent", "Override that header");
  fetcher->SetHeader("Authorization", "Basic user:passwd");

  // Invalid headers.
  fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
  fetcher->SetHeader("X-Bar: ", "I do not know how to parse");

  // Hide Accept header normally added by default.
  fetcher->SetHeader("Accept", "");

  PythonHttpServer server;
  int port = server.GetPort();
  ASSERT_TRUE(server.started_);

  this->loop_.PostTask(
      FROM_HERE,
      base::Bind(StartTransfer,
                 fetcher.get(),
                 LocalServerUrlForPath(port, "/echo-headers")));
  this->loop_.Run();

  EXPECT_NE(string::npos,
            delegate.data.find("user-agent: Override that header\r\n"));
  EXPECT_NE(string::npos,
            delegate.data.find("Authorization: Basic user:passwd\r\n"));

  EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
  EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
  EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
}

class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
 public:
  bool ReceivedBytes(HttpFetcher* fetcher,
                     const void* /* bytes */,
                     size_t /* length */) override {
    CHECK(!paused_);
    paused_ = true;
    fetcher->Pause();
    return true;
  }
  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
    MessageLoop::current()->BreakLoop();
  }
  void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
  void Unpause() {
    CHECK(paused_);
    paused_ = false;
    fetcher_->Unpause();
  }
  bool paused_;
  HttpFetcher* fetcher_;
};

void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
                              MessageLoop::TaskId* my_id) {
  if (delegate->paused_)
    delegate->Unpause();
  // Update the task id with the new scheduled callback.
  *my_id = MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
      base::TimeDelta::FromMilliseconds(200));
}

TYPED_TEST(HttpFetcherTest, PauseTest) {
  PausingHttpFetcherTestDelegate delegate;
  unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
  delegate.paused_ = false;
  delegate.fetcher_ = fetcher.get();
  fetcher->set_delegate(&delegate);

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  MessageLoop::TaskId callback_id{};
  callback_id = this->loop_.PostDelayedTask(
      FROM_HERE,
      base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
      base::TimeDelta::FromMilliseconds(200));
  fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));

  this->loop_.Run();
  EXPECT_TRUE(this->loop_.CancelTask(callback_id));
}

// This test will pause the fetcher while the download is not yet started
// because it is waiting for the proxy to be resolved.
TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
    return;
  unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());

  // Saved arguments from the proxy call.
  fetcher->BeginTransfer("http://fake_url");

  // Pausing and unpausing while resolving the proxy should not affect anything.
  fetcher->Pause();
  fetcher->Unpause();
  fetcher->Pause();
  // Proxy resolver comes back after we paused the fetcher.
}

class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
 public:
  bool ReceivedBytes(HttpFetcher* fetcher,
                     const void* bytes,
                     size_t length) override {
    return true;
  }
  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
    ADD_FAILURE();  // We should never get here
    MessageLoop::current()->BreakLoop();
  }
  void TransferTerminated(HttpFetcher* fetcher) override {
    EXPECT_EQ(fetcher, fetcher_.get());
    EXPECT_FALSE(once_);
    EXPECT_TRUE(callback_once_);
    callback_once_ = false;
    // The fetcher could have a callback scheduled on the ProxyResolver that
    // can fire after this callback. We wait until the end of the test to
    // delete the fetcher.
  }
  void TerminateTransfer() {
    CHECK(once_);
    once_ = false;
    fetcher_->TerminateTransfer();
  }
  void EndLoop() { MessageLoop::current()->BreakLoop(); }
  bool once_;
  bool callback_once_;
  unique_ptr<HttpFetcher> fetcher_;
};

void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
                             MessageLoop::TaskId* my_id) {
  if (delegate->once_) {
    delegate->TerminateTransfer();
    *my_id = MessageLoop::current()->PostTask(
        FROM_HERE, base::Bind(AbortingTimeoutCallback, delegate, my_id));
  } else {
    delegate->EndLoop();
    *my_id = MessageLoop::kTaskIdNull;
  }
}

TYPED_TEST(HttpFetcherTest, AbortTest) {
  AbortingHttpFetcherTestDelegate delegate;
  delegate.fetcher_.reset(this->test_.NewLargeFetcher());
  delegate.once_ = true;
  delegate.callback_once_ = true;
  delegate.fetcher_->set_delegate(&delegate);

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  this->test_.IgnoreServerAborting(server.get());
  ASSERT_TRUE(server->started_);

  MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;

  task_id = this->loop_.PostTask(
      FROM_HERE, base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
  delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));

  this->loop_.Run();
  CHECK(!delegate.once_);
  CHECK(!delegate.callback_once_);
  this->loop_.CancelTask(task_id);
}

TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
    return;
  unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());

  HttpFetcherTestDelegate delegate;
  fetcher->set_delegate(&delegate);

  fetcher->BeginTransfer("http://fake_url");
  // Run the message loop until idle. This must call the MockProxyResolver with
  // the request.
  while (this->loop_.RunOnce(false)) {
  }

  // Terminate the transfer right before the proxy resolution response.
  fetcher->TerminateTransfer();
  EXPECT_EQ(0, delegate.times_received_bytes_called_);
  EXPECT_EQ(0, delegate.times_transfer_complete_called_);
  EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
}

class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
 public:
  bool ReceivedBytes(HttpFetcher* fetcher,
                     const void* bytes,
                     size_t length) override {
    data.append(reinterpret_cast<const char*>(bytes), length);
    return true;
  }
  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
    EXPECT_TRUE(successful);
    EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
    MessageLoop::current()->BreakLoop();
  }
  void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
  string data;
};

TYPED_TEST(HttpFetcherTest, FlakyTest) {
  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
    return;
  {
    FlakyHttpFetcherTestDelegate delegate;
    unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
    fetcher->set_delegate(&delegate);

    unique_ptr<HttpServer> server(this->test_.CreateServer());
    ASSERT_TRUE(server->started_);

    this->loop_.PostTask(FROM_HERE,
                         base::Bind(&StartTransfer,
                                    fetcher.get(),
                                    LocalServerUrlForPath(
                                        server->GetPort(),
                                        base::StringPrintf("/flaky/%d/%d/%d/%d",
                                                           kBigLength,
                                                           kFlakyTruncateLength,
                                                           kFlakySleepEvery,
                                                           kFlakySleepSecs))));
    this->loop_.Run();

    // verify the data we get back
    ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
    for (int i = 0; i < kBigLength; i += 10) {
      // Assert so that we don't flood the screen w/ EXPECT errors on failure.
      ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
    }
  }
}

// This delegate kills the server attached to it after receiving any bytes.
// This can be used for testing what happens when you try to fetch data and
// the server dies.
class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
 public:
  explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
      : server_(server) {}

  ~FailureHttpFetcherTestDelegate() override {
    if (server_) {
      LOG(INFO) << "Stopping server in destructor";
      server_.reset();
      LOG(INFO) << "server stopped";
    }
  }

  bool ReceivedBytes(HttpFetcher* fetcher,
                     const void* bytes,
                     size_t length) override {
    if (server_) {
      LOG(INFO) << "Stopping server in ReceivedBytes";
      server_.reset();
      LOG(INFO) << "server stopped";
    }
    return true;
  }
  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
    EXPECT_FALSE(successful);
    EXPECT_EQ(0, fetcher->http_response_code());
    times_transfer_complete_called_++;
    MessageLoop::current()->BreakLoop();
  }
  void TransferTerminated(HttpFetcher* fetcher) override {
    times_transfer_terminated_called_++;
    MessageLoop::current()->BreakLoop();
  }
  unique_ptr<PythonHttpServer> server_;
  int times_transfer_terminated_called_{0};
  int times_transfer_complete_called_{0};
};

TYPED_TEST(HttpFetcherTest, FailureTest) {
  // This test ensures that a fetcher responds correctly when a server isn't
  // available at all.
  if (this->test_.IsMock())
    return;
  FailureHttpFetcherTestDelegate delegate(nullptr);
  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
  fetcher->set_delegate(&delegate);

  this->loop_.PostTask(
      FROM_HERE,
      base::Bind(
          StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
  this->loop_.Run();
  EXPECT_EQ(1, delegate.times_transfer_complete_called_);
  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);

  // Exiting and testing happens in the delegate
}

TYPED_TEST(HttpFetcherTest, NoResponseTest) {
  // This test starts a new http server but the server doesn't respond and just
  // closes the connection.
  if (this->test_.IsMock())
    return;

  PythonHttpServer* server = new PythonHttpServer();
  int port = server->GetPort();
  ASSERT_TRUE(server->started_);

  // Handles destruction and claims ownership.
  FailureHttpFetcherTestDelegate delegate(server);
  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
  fetcher->set_delegate(&delegate);
  // The server will not reply at all, so we can limit the execution time of the
  // test by reducing the low-speed timeout to something small. The test will
  // finish once the TimeoutCallback() triggers (every second) and the timeout
  // expired.
  fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);

  this->loop_.PostTask(
      FROM_HERE,
      base::Bind(
          StartTransfer, fetcher.get(), LocalServerUrlForPath(port, "/hang")));
  this->loop_.Run();
  EXPECT_EQ(1, delegate.times_transfer_complete_called_);
  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);

  // Check that no other callback runs in the next two seconds. That would
  // indicate a leaked callback.
  bool timeout = false;
  auto callback = base::Bind([](bool* timeout) { *timeout = true; },
                             base::Unretained(&timeout));
  this->loop_.PostDelayedTask(
      FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
  EXPECT_TRUE(this->loop_.RunOnce(true));
  EXPECT_TRUE(timeout);
}

TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
  // This test starts a new http server and kills it after receiving its first
  // set of bytes. It test whether or not our fetcher eventually gives up on
  // retries and aborts correctly.
  if (this->test_.IsMock())
    return;
  PythonHttpServer* server = new PythonHttpServer();
  int port = server->GetPort();
  ASSERT_TRUE(server->started_);

  // Handles destruction and claims ownership.
  FailureHttpFetcherTestDelegate delegate(server);
  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
  fetcher->set_delegate(&delegate);

  this->loop_.PostTask(
      FROM_HERE,
      base::Bind(StartTransfer,
                 fetcher.get(),
                 LocalServerUrlForPath(port,
                                       base::StringPrintf("/flaky/%d/%d/%d/%d",
                                                          kBigLength,
                                                          kFlakyTruncateLength,
                                                          kFlakySleepEvery,
                                                          kFlakySleepSecs))));
  this->loop_.Run();
  EXPECT_EQ(1, delegate.times_transfer_complete_called_);
  EXPECT_EQ(0, delegate.times_transfer_terminated_called_);

  // Exiting and testing happens in the delegate
}

// Test that we can cancel a transfer while it is still trying to connect to the
// server. This test kills the server after a few bytes are received.
TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
    return;

  PythonHttpServer* server = new PythonHttpServer();
  int port = server->GetPort();
  ASSERT_TRUE(server->started_);

  // Handles destruction and claims ownership.
  FailureHttpFetcherTestDelegate delegate(server);
  unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
  fetcher->set_delegate(&delegate);

  this->loop_.PostTask(
      FROM_HERE,
      base::Bind(StartTransfer,
                 fetcher.get(),
                 LocalServerUrlForPath(port,
                                       base::StringPrintf("/flaky/%d/%d/%d/%d",
                                                          kBigLength,
                                                          kFlakyTruncateLength,
                                                          kFlakySleepEvery,
                                                          kFlakySleepSecs))));
  // Terminating the transfer after 3 seconds gives it a chance to contact the
  // server and enter the retry loop.
  this->loop_.PostDelayedTask(FROM_HERE,
                              base::Bind(&HttpFetcher::TerminateTransfer,
                                         base::Unretained(fetcher.get())),
                              base::TimeDelta::FromSeconds(3));

  // Exiting and testing happens in the delegate.
  this->loop_.Run();
  EXPECT_EQ(0, delegate.times_transfer_complete_called_);
  EXPECT_EQ(1, delegate.times_transfer_terminated_called_);

  // Check that no other callback runs in the next two seconds. That would
  // indicate a leaked callback.
  bool timeout = false;
  auto callback = base::Bind([](bool* timeout) { *timeout = true; },
                             base::Unretained(&timeout));
  this->loop_.PostDelayedTask(
      FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
  EXPECT_TRUE(this->loop_.RunOnce(true));
  EXPECT_TRUE(timeout);
}

const HttpResponseCode kRedirectCodes[] = {kHttpResponseMovedPermanently,
                                           kHttpResponseFound,
                                           kHttpResponseSeeOther,
                                           kHttpResponseTempRedirect};

class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
 public:
  explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
      : expected_successful_(expected_successful) {}
  bool ReceivedBytes(HttpFetcher* fetcher,
                     const void* bytes,
                     size_t length) override {
    data.append(reinterpret_cast<const char*>(bytes), length);
    return true;
  }
  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
    EXPECT_EQ(expected_successful_, successful);
    if (expected_successful_) {
      EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
    } else {
      EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
      EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
    }
    MessageLoop::current()->BreakLoop();
  }
  void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
  bool expected_successful_;
  string data;
};

// RedirectTest takes ownership of |http_fetcher|.
void RedirectTest(const HttpServer* server,
                  bool expected_successful,
                  const string& url,
                  HttpFetcher* http_fetcher) {
  RedirectHttpFetcherTestDelegate delegate(expected_successful);
  unique_ptr<HttpFetcher> fetcher(http_fetcher);
  fetcher->set_delegate(&delegate);

  MessageLoop::current()->PostTask(
      FROM_HERE,
      base::Bind(StartTransfer,
                 fetcher.get(),
                 LocalServerUrlForPath(server->GetPort(), url)));
  MessageLoop::current()->Run();
  if (expected_successful) {
    // verify the data we get back
    ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
    for (int i = 0; i < kMediumLength; i += 10) {
      // Assert so that we don't flood the screen w/ EXPECT errors on failure.
      ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
    }
  }
}

TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  for (size_t c = 0; c < base::size(kRedirectCodes); ++c) {
    const string url = base::StringPrintf(
        "/redirect/%d/download/%d", kRedirectCodes[c], kMediumLength);
    RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
  }
}

TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  string url;
  for (int r = 0; r < kDownloadMaxRedirects; r++) {
    url += base::StringPrintf("/redirect/%d",
                              kRedirectCodes[r % base::size(kRedirectCodes)]);
  }
  url += base::StringPrintf("/download/%d", kMediumLength);
  RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
}

TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
  if (this->test_.IsMock() || !this->test_.IsHttpSupported())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  string url;
  for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
    url += base::StringPrintf("/redirect/%d",
                              kRedirectCodes[r % base::size(kRedirectCodes)]);
  }
  url += base::StringPrintf("/download/%d", kMediumLength);
  RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
}

class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
 public:
  explicit MultiHttpFetcherTestDelegate(int expected_response_code)
      : expected_response_code_(expected_response_code) {}

  bool ReceivedBytes(HttpFetcher* fetcher,
                     const void* bytes,
                     size_t length) override {
    EXPECT_EQ(fetcher, fetcher_.get());
    data.append(reinterpret_cast<const char*>(bytes), length);
    return true;
  }

  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
    EXPECT_EQ(fetcher, fetcher_.get());
    EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
    if (expected_response_code_ != 0)
      EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
    // Destroy the fetcher (because we're allowed to).
    fetcher_.reset(nullptr);
    MessageLoop::current()->BreakLoop();
  }

  void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }

  unique_ptr<HttpFetcher> fetcher_;
  int expected_response_code_;
  string data;
};

void MultiTest(HttpFetcher* fetcher_in,
               FakeHardware* fake_hardware,
               const string& url,
               const vector<pair<off_t, off_t>>& ranges,
               const string& expected_prefix,
               size_t expected_size,
               HttpResponseCode expected_response_code) {
  MultiHttpFetcherTestDelegate delegate(expected_response_code);
  delegate.fetcher_.reset(fetcher_in);

  MultiRangeHttpFetcher* multi_fetcher =
      static_cast<MultiRangeHttpFetcher*>(fetcher_in);
  ASSERT_TRUE(multi_fetcher);
  multi_fetcher->ClearRanges();
  for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
                                                  e = ranges.end();
       it != e;
       ++it) {
    string tmp_str = base::StringPrintf("%jd+", it->first);
    if (it->second > 0) {
      base::StringAppendF(&tmp_str, "%jd", it->second);
      multi_fetcher->AddRange(it->first, it->second);
    } else {
      base::StringAppendF(&tmp_str, "?");
      multi_fetcher->AddRange(it->first);
    }
    LOG(INFO) << "added range: " << tmp_str;
  }
  fake_hardware->SetIsOfficialBuild(false);
  multi_fetcher->set_delegate(&delegate);

  MessageLoop::current()->PostTask(
      FROM_HERE, base::Bind(StartTransfer, multi_fetcher, url));
  MessageLoop::current()->Run();

  EXPECT_EQ(expected_size, delegate.data.size());
  EXPECT_EQ(expected_prefix,
            string(delegate.data.data(), expected_prefix.size()));
}

TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
  if (!this->test_.IsMulti())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  vector<pair<off_t, off_t>> ranges;
  ranges.push_back(make_pair(0, 25));
  ranges.push_back(make_pair(99, 17));
  MultiTest(this->test_.NewLargeFetcher(),
            this->test_.fake_hardware(),
            this->test_.BigUrl(server->GetPort()),
            ranges,
            "abcdefghijabcdefghijabcdejabcdefghijabcdef",
            25 + 17,
            this->test_.IsFileFetcher() ? kHttpResponseOk
                                        : kHttpResponsePartialContent);
}

TYPED_TEST(HttpFetcherTest, MultiHttpFetcherUnspecifiedEndTest) {
  if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  vector<pair<off_t, off_t>> ranges;
  ranges.push_back(make_pair(0, 25));
  ranges.push_back(make_pair(99, 0));
  MultiTest(this->test_.NewLargeFetcher(),
            this->test_.fake_hardware(),
            this->test_.BigUrl(server->GetPort()),
            ranges,
            "abcdefghijabcdefghijabcdejabcdefghijabcdef",
            kBigLength - (99 - 25),
            kHttpResponsePartialContent);
}

TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
  if (!this->test_.IsMulti())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  vector<pair<off_t, off_t>> ranges;
  ranges.push_back(make_pair(0, 24));
  MultiTest(this->test_.NewLargeFetcher(),
            this->test_.fake_hardware(),
            this->test_.BigUrl(server->GetPort()),
            ranges,
            "abcdefghijabcdefghijabcd",
            24,
            this->test_.IsFileFetcher() ? kHttpResponseOk
                                        : kHttpResponsePartialContent);
}

TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
  if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  vector<pair<off_t, off_t>> ranges;
  ranges.push_back(make_pair(kBigLength - 2, 0));
  ranges.push_back(make_pair(kBigLength - 3, 0));
  MultiTest(this->test_.NewLargeFetcher(),
            this->test_.fake_hardware(),
            this->test_.BigUrl(server->GetPort()),
            ranges,
            "ijhij",
            5,
            kHttpResponsePartialContent);
}

TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
  if (!this->test_.IsMulti())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  vector<pair<off_t, off_t>> ranges;
  ranges.push_back(make_pair(kBigLength - 2, 4));
  for (int i = 0; i < 2; ++i) {
    LOG(INFO) << "i = " << i;
    MultiTest(this->test_.NewLargeFetcher(),
              this->test_.fake_hardware(),
              this->test_.BigUrl(server->GetPort()),
              ranges,
              "ij",
              2,
              kHttpResponseUndefined);
    ranges.push_back(make_pair(0, 5));
  }
}

// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
// should retry with other proxies listed before giving up.
//
// (1) successful recovery: The offset fetch will fail twice but succeed with
// the third proxy.
TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
  if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  vector<pair<off_t, off_t>> ranges;
  ranges.push_back(make_pair(0, 25));
  ranges.push_back(make_pair(99, 0));
  MultiTest(this->test_.NewLargeFetcher(3),
            this->test_.fake_hardware(),
            LocalServerUrlForPath(
                server->GetPort(),
                base::StringPrintf("/error-if-offset/%d/2", kBigLength)),
            ranges,
            "abcdefghijabcdefghijabcdejabcdefghijabcdef",
            kBigLength - (99 - 25),
            kHttpResponsePartialContent);
}

// (2) unsuccessful recovery: The offset fetch will fail repeatedly.  The
// fetcher will signal a (failed) completed transfer to the delegate.
TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
  if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
    return;

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  vector<pair<off_t, off_t>> ranges;
  ranges.push_back(make_pair(0, 25));
  ranges.push_back(make_pair(99, 0));
  MultiTest(this->test_.NewLargeFetcher(),
            this->test_.fake_hardware(),
            LocalServerUrlForPath(
                server->GetPort(),
                base::StringPrintf("/error-if-offset/%d/3", kBigLength)),
            ranges,
            "abcdefghijabcdefghijabcde",  // only received the first chunk
            25,
            kHttpResponseUndefined);
}

// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
 public:
  explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
      : terminate_trigger_bytes_(terminate_trigger_bytes) {}

  bool ReceivedBytes(HttpFetcher* fetcher,
                     const void* bytes,
                     size_t length) override {
    LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
    EXPECT_EQ(fetcher, fetcher_.get());
    bool should_terminate = false;
    if (bytes_downloaded_ < terminate_trigger_bytes_ &&
        bytes_downloaded_ + length >= terminate_trigger_bytes_) {
      MessageLoop::current()->PostTask(
          FROM_HERE,
          base::Bind(&HttpFetcher::TerminateTransfer,
                     base::Unretained(fetcher_.get())));
      should_terminate = true;
    }
    bytes_downloaded_ += length;
    return !should_terminate;
  }

  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
    ADD_FAILURE() << "TransferComplete called but expected a failure";
    // Destroy the fetcher (because we're allowed to).
    fetcher_.reset(nullptr);
    MessageLoop::current()->BreakLoop();
  }

  void TransferTerminated(HttpFetcher* fetcher) override {
    // Destroy the fetcher (because we're allowed to).
    fetcher_.reset(nullptr);
    MessageLoop::current()->BreakLoop();
  }

  unique_ptr<HttpFetcher> fetcher_;
  size_t bytes_downloaded_{0};
  size_t terminate_trigger_bytes_;
};

TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
  if (!this->test_.IsMulti())
    return;
  const size_t kRangeTrigger = 1000;
  MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);

  unique_ptr<HttpServer> server(this->test_.CreateServer());
  ASSERT_TRUE(server->started_);

  MultiRangeHttpFetcher* multi_fetcher =
      static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
  ASSERT_TRUE(multi_fetcher);
  // Transfer ownership of the fetcher to the delegate.
  delegate.fetcher_.reset(multi_fetcher);
  multi_fetcher->set_delegate(&delegate);

  multi_fetcher->ClearRanges();
  multi_fetcher->AddRange(45, kRangeTrigger);
  multi_fetcher->AddRange(2000, 100);

  this->test_.fake_hardware()->SetIsOfficialBuild(false);

  StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
  MessageLoop::current()->Run();

  // Check that the delegate made it to the trigger point.
  EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
}

class BlockedTransferTestDelegate : public HttpFetcherDelegate {
 public:
  bool ReceivedBytes(HttpFetcher* fetcher,
                     const void* bytes,
                     size_t length) override {
    ADD_FAILURE();
    return true;
  }
  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
    EXPECT_FALSE(successful);
    MessageLoop::current()->BreakLoop();
  }
  void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
};

void BlockedTransferTestHelper(AnyHttpFetcherFactory* fetcher_test,
                               bool is_official_build) {
  if (fetcher_test->IsMock() || fetcher_test->IsMulti())
    return;

  unique_ptr<HttpServer> server(fetcher_test->CreateServer());
  ASSERT_TRUE(server->started_);

  BlockedTransferTestDelegate delegate;
  unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
  LOG(INFO) << "is_official_build: " << is_official_build;
  // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
  fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
  fetcher->set_delegate(&delegate);

  MessageLoop::current()->PostTask(
      FROM_HERE,
      base::Bind(
          StartTransfer,
          fetcher.get(),
          LocalServerUrlForPath(server->GetPort(),
                                fetcher_test->SmallUrl(server->GetPort()))));
  MessageLoop::current()->Run();
}

TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
  BlockedTransferTestHelper(&this->test_, false);
}

TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
  BlockedTransferTestHelper(&this->test_, true);
}

}  // namespace

}  // namespace chromeos_update_engine
