// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <fuchsia/net/oldhttp/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>

#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/service_directory.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "fuchsia/http/http_service_impl.h"
#include "fuchsia/http/url_loader_impl.h"
#include "net/base/net_errors.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace oldhttp = ::fuchsia::net::oldhttp;

namespace {

const base::FilePath::CharType kTestFilePath[] =
    FILE_PATH_LITERAL("fuchsia/http/testdata");

// Capacity, in bytes, for buffers used to read data off the URLResponse.
const size_t kBufferCapacity = 1024;

using ResponseHeaders = std::multimap<std::string, std::string>;

class HttpServiceTest : public ::testing::Test {
 public:
  HttpServiceTest()
      : task_environment_(
            base::test::ScopedTaskEnvironment::MainThreadType::IO_MOCK_TIME),
        binding_(&http_service_server_) {
    // Initialize the test server.
    test_server_.AddDefaultHandlers(
        base::FilePath(FILE_PATH_LITERAL(kTestFilePath)));
    net::test_server::RegisterDefaultHandlers(&test_server_);
  }

 protected:
  base::test::ScopedTaskEnvironment task_environment_;

  void SetUp() override {
    ASSERT_TRUE(test_server_.Start());

    // Bind the service with the client-side interface.
    binding_.Bind(http_service_interface_.NewRequest());
  }

  void TearDown() override {
    // Disconnect the client and wait for the service to shut down.
    base::RunLoop run_loop;
    binding_.set_error_handler(
        [&run_loop](zx_status_t status) { run_loop.Quit(); });
    http_service_interface_.Unbind();
    run_loop.Run();
    binding_.set_error_handler(nullptr);

    // Check there are no pending requests.
    EXPECT_EQ(URLLoaderImpl::GetNumActiveRequestsForTests(), 0);
  }

  // Helper method to start |request| on |url_loader|
  void ExecuteRequest(const oldhttp::URLLoaderPtr& url_loader,
                      oldhttp::URLRequest request) {
    base::RunLoop run_loop;

    url_loader->Start(std::move(request),
                      [this, &run_loop](oldhttp::URLResponse response) {
                        run_loop.Quit();
                        url_response_ = std::move(response);
                      });
    run_loop.Run();
  }

  net::EmbeddedTestServer* http_test_server() { return &test_server_; }
  oldhttp::HttpServicePtr& http_service() { return http_service_interface_; }
  oldhttp::URLResponse& url_response() { return url_response_; }

 private:
  net::EmbeddedTestServer test_server_;

  HttpServiceImpl http_service_server_;
  oldhttp::HttpServicePtr http_service_interface_;
  fidl::Binding<oldhttp::HttpService> binding_;
  oldhttp::URLResponse url_response_;

  DISALLOW_COPY_AND_ASSIGN(HttpServiceTest);
};

class TestZxHandleWatcher : public base::MessagePumpFuchsia::ZxHandleWatcher {
 public:
  explicit TestZxHandleWatcher(base::OnceClosure on_signaled)
      : on_signaled_(std::move(on_signaled)) {}
  ~TestZxHandleWatcher() override = default;

  // ZxHandleWatcher implementation.
  void OnZxHandleSignalled(zx_handle_t handle, zx_signals_t signals) override {
    signals_ = signals;
    std::move(on_signaled_).Run();
  }

  zx_signals_t signals() { return signals_; }

 protected:
  base::OnceClosure on_signaled_;
  zx_signals_t signals_ = 0;
};

// Runs MessageLoop until one of the specified |signals| is signaled on the
// |handle|. Return observed signals.
zx_signals_t RunLoopUntilSignal(zx_handle_t handle, zx_signals_t signals) {
  base::RunLoop run_loop;
  TestZxHandleWatcher watcher(run_loop.QuitClosure());
  base::MessagePumpForIO::ZxHandleWatchController watch_contoller(FROM_HERE);

  base::MessageLoopCurrentForIO::Get()->WatchZxHandle(
      handle, /*persistent=*/false, signals, &watch_contoller, &watcher);
  run_loop.Run();

  return watcher.signals();
}

void CheckResponseStream(const oldhttp::URLResponse& response,
                         const std::string& expected_response) {
  EXPECT_TRUE(response.body->is_stream());

  zx::socket stream = std::move(response.body->stream());
  size_t offset = 0;

  while (true) {
    std::array<char, kBufferCapacity> buffer;
    size_t size = 0;
    zx_status_t result = stream.read(0, buffer.data(), kBufferCapacity, &size);

    if (result == ZX_ERR_SHOULD_WAIT) {
      zx_signals_t signals = RunLoopUntilSignal(
          stream.get(), ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED);

      if (signals & ZX_SOCKET_READABLE) {
        // Attempt to read again now that the socket is readable.
        continue;
      } else if (signals & ZX_SOCKET_PEER_CLOSED) {
        // Done reading.
        break;
      } else {
        NOTREACHED();
      }
    } else if (result == ZX_ERR_PEER_CLOSED) {
      // Done reading.
      break;
    }
    EXPECT_EQ(result, ZX_OK);

    EXPECT_TRUE(std::equal(buffer.begin(), buffer.begin() + size,
                           expected_response.begin() + offset));
    offset += size;
  }

  EXPECT_EQ(offset, expected_response.length());
}

void CheckResponseBuffer(const oldhttp::URLResponse& response,
                         const std::string& expected_response) {
  EXPECT_TRUE(response.body->is_buffer());

  fuchsia::mem::Buffer mem_buffer = std::move(response.body->buffer());
  size_t response_size = mem_buffer.size;
  EXPECT_EQ(mem_buffer.size, expected_response.length());

  std::array<char, kBufferCapacity> buffer;
  size_t offset = 0;
  while (offset != mem_buffer.size) {
    size_t length = std::min(response_size - offset, kBufferCapacity);
    zx_status_t result = mem_buffer.vmo.read(buffer.data(), offset, length);
    EXPECT_EQ(result, ZX_OK);

    EXPECT_TRUE(std::equal(buffer.begin(), buffer.begin() + response_size,
                           expected_response.begin() + offset));
    offset += response_size;
  }

  EXPECT_EQ(offset, expected_response.length());
}

void CheckResponseHeaders(const oldhttp::URLResponse& response,
                          ResponseHeaders* expected_headers) {
  for (auto& header : response.headers.get()) {
    const std::string header_name = header.name.data();
    const std::string header_value = header.value.data();
    auto iter = std::find_if(expected_headers->begin(), expected_headers->end(),
                             [&header_name, &header_value](auto& elt) -> bool {
                               return elt.first.compare(header_name) == 0 &&
                                      elt.second.compare(header_value) == 0;
                             });
    EXPECT_NE(iter, expected_headers->end())
        << "Unexpected header: \"" << header_name << "\" with value: \""
        << header_value << "\".";
    if (iter != expected_headers->end()) {
      expected_headers->erase(iter);
    }
  }
  EXPECT_TRUE(expected_headers->empty());
}

}  // namespace

// Check a basic end-to-end request resolution with the response being streamed
// is handled properly.
TEST_F(HttpServiceTest, BasicRequestStream) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());

  oldhttp::URLRequest request;
  request.url = http_test_server()->GetURL("/simple.html").spec();
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::STREAM;

  ExecuteRequest(url_loader, std::move(request));
  EXPECT_EQ(url_response().status_code, 200u);
  CheckResponseStream(url_response(), "hello");
}

// Check a basic end-to-end request resolution with the response being
// buffered is handled properly.
TEST_F(HttpServiceTest, BasicRequestBuffer) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());

  oldhttp::URLRequest request;
  request.url = http_test_server()->GetURL("/simple.html").spec();
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::BUFFER;

  ExecuteRequest(url_loader, std::move(request));
  EXPECT_EQ(url_response().status_code, 200u);
  CheckResponseBuffer(url_response(), "hello");
}

// Check network request headers are received properly.
TEST_F(HttpServiceTest, RequestWithHeaders) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());

  oldhttp::URLRequest request;
  request.url = http_test_server()->GetURL("/with-headers.html").spec();
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::STREAM;

  ExecuteRequest(url_loader, std::move(request));
  EXPECT_EQ(url_response().status_code, 200u);
  CheckResponseStream(
      url_response(),
      "This file is boring; all the action's in the .mock-http-headers.\n");
  ResponseHeaders expected_headers = {
      {"Cache-Control", "private"},
      {"Content-Type", "text/html; charset=ISO-8859-1"},
      {"X-Multiple-Entries", "a"},
      {"X-Multiple-Entries", "b"},
  };
  CheckResponseHeaders(url_response(), &expected_headers);
}

// Check duplicate network request headers are received properly.
TEST_F(HttpServiceTest, RequestWithDuplicateHeaders) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());

  oldhttp::URLRequest request;
  request.url =
      http_test_server()->GetURL("/with-duplicate-headers.html").spec();
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::STREAM;

  ExecuteRequest(url_loader, std::move(request));
  EXPECT_EQ(url_response().status_code, 200u);
  CheckResponseStream(
      url_response(),
      "This file is boring; all the action's in the .mock-http-headers.\n");
  ResponseHeaders expected_headers = {
      {"Cache-Control", "private"},
      {"Content-Type", "text/html; charset=ISO-8859-1"},
      {"X-Multiple-Entries", "a"},
      {"X-Multiple-Entries", "a"},
      {"X-Multiple-Entries", "b"},
  };
  CheckResponseHeaders(url_response(), &expected_headers);
}

// Check a request with automatic redirect resolution is handled properly.
TEST_F(HttpServiceTest, AutoRedirect) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());

  oldhttp::URLRequest request;
  request.url = http_test_server()->GetURL("/redirect-test.html").spec();
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::STREAM;
  request.auto_follow_redirects = true;

  ExecuteRequest(url_loader, std::move(request));
  EXPECT_EQ(url_response().status_code, 200u);
  EXPECT_EQ(url_response().url,
            http_test_server()->GetURL("/with-headers.html").spec());
}

// Check a request with manual redirect resolution is handled properly.
TEST_F(HttpServiceTest, ManualRedirect) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());
  std::string request_url =
      http_test_server()->GetURL("/redirect-test.html").spec();

  oldhttp::URLRequest request;
  request.url = request_url;
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::STREAM;
  request.auto_follow_redirects = false;

  ExecuteRequest(url_loader, std::move(request));
  std::string final_url =
      http_test_server()->GetURL("/with-headers.html").spec();
  EXPECT_EQ(url_response().status_code, 302u);
  EXPECT_EQ(url_response().url, request_url);
  EXPECT_EQ(url_response().redirect_url, final_url);

  base::RunLoop run_loop;
  url_loader->FollowRedirect(
      [&run_loop, &final_url](oldhttp::URLResponse response) {
        EXPECT_EQ(response.status_code, 200u);
        EXPECT_EQ(response.url, final_url);
        run_loop.Quit();
      });
  run_loop.Run();
}

// Check HTTP error codes are properly populated.
TEST_F(HttpServiceTest, HttpErrorCode) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());

  oldhttp::URLRequest request;
  request.url = http_test_server()
                    ->base_url()
                    .Resolve("/non_existent_cooper.html")
                    .spec();
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::STREAM;

  ExecuteRequest(url_loader, std::move(request));
  EXPECT_EQ(url_response().status_code, 404u);
}

// Check network error codes are properly populated.
TEST_F(HttpServiceTest, InvalidURL) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());

  oldhttp::URLRequest request;
  request.url = "ht\\tp://test.test/";
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::STREAM;

  ExecuteRequest(url_loader, std::move(request));
  EXPECT_EQ(url_response().error->code, net::ERR_INVALID_URL);
}

// Ensure the service can handle multiple concurrent requests.
TEST_F(HttpServiceTest, MultipleRequests) {
  oldhttp::URLLoaderPtr url_loaders[100];
  for (int i = 0; i < 100; i++) {
    http_service()->CreateURLLoader(url_loaders[i].NewRequest());
  }

  base::RunLoop run_loop;
  int requests_done = 0;
  for (int i = 0; i < 100; i++) {
    oldhttp::URLRequest request;
    request.url = http_test_server()->GetURL("/simple.html").spec();
    request.method = "GET";
    request.response_body_mode = (i % 2) == 0
                                     ? oldhttp::ResponseBodyMode::STREAM
                                     : oldhttp::ResponseBodyMode::BUFFER;
    url_loaders[i]->Start(
        std::move(request),
        [&requests_done, &run_loop](oldhttp::URLResponse response) {
          EXPECT_EQ(response.status_code, 200u);
          if (response.body->is_buffer()) {
            CheckResponseBuffer(response, "hello");
          } else {
            CheckResponseStream(response, "hello");
          }
          requests_done++;
          if (requests_done == 100) {
            // Last request signals the run_loop to exit.
            run_loop.Quit();
          }
        });
  }
  run_loop.Run();
}

// Check QueryStatus works as expected when a request is loading.
// Also checks the request is properly deleted after the binding is destroyed.
TEST_F(HttpServiceTest, QueryStatus) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());

  oldhttp::URLRequest request;
  request.url = http_test_server()->GetURL("/hung-after-headers").spec();
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::STREAM;

  // In socket mode, we should still get the response headers.
  ExecuteRequest(url_loader, std::move(request));
  EXPECT_EQ(url_response().status_code, 200u);

  base::RunLoop run_loop;
  url_loader->QueryStatus([&run_loop](oldhttp::URLLoaderStatus status) {
    EXPECT_TRUE(status.is_loading);
    run_loop.Quit();
  });
  run_loop.Run();
}

// Check the response error is properly set if the server disconnects early.
TEST_F(HttpServiceTest, CloseSocket) {
  oldhttp::URLLoaderPtr url_loader;
  http_service()->CreateURLLoader(url_loader.NewRequest());

  oldhttp::URLRequest request;
  request.url = http_test_server()->GetURL("/close-socket").spec();
  request.method = "GET";
  request.response_body_mode = oldhttp::ResponseBodyMode::STREAM;

  ExecuteRequest(url_loader, std::move(request));
  EXPECT_EQ(url_response().error->code, net::ERR_EMPTY_RESPONSE);
}
