// 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/component_context.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 "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"
#include "webrunner/net_http/http_service_impl.h"
#include "webrunner/net_http/url_loader_impl.h"

namespace net_http {

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

namespace {

const base::FilePath::CharType kTestFilePath[] =
    FILE_PATH_LITERAL("webrunner/net_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);
}

}  // namespace net_http
