// Copyright 2019 The Fuchsia 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 "src/developer/cmd/console.h"

#include <fcntl.h>
#include <fuchsia/hardware/pty/c/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/io.h>
#include <lib/fit/function.h>
#include <lib/zx/channel.h>
#include <lib/zx/socket.h>
#include <poll.h>
#include <unistd.h>
#include <zircon/status.h>

#include <utility>

#include <fbl/unique_fd.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "src/lib/testing/loop_fixture/real_loop_fixture.h"

namespace {

using Console = gtest::RealLoopFixture;

class CallbackClient : public cmd::Console::Client {
 public:
  ~CallbackClient() override = default;

  zx_status_t OnConsoleCommand(cmd::Command command) override {
    return console_command_callback(std::move(command));
  }
  void OnConsoleInterrupt() override { console_interrupt_callback(); }
  void OnConsoleError(zx_status_t status) override { console_error_callback(status); }
  void OnConsoleAutocomplete(cmd::Autocomplete* autocomplete) override {
    return console_autocomplete_callback(autocomplete);
  }

  fit::function<zx_status_t(cmd::Command)> console_command_callback;
  fit::closure console_interrupt_callback;
  fit::function<void(zx_status_t status)> console_error_callback;
  fit::function<void(cmd::Autocomplete* autocomplete)> console_autocomplete_callback;
};

TEST_F(Console, Control) {
  zx::socket h0, h1;
  EXPECT_EQ(ZX_OK, zx::socket::create(0, &h0, &h1));

  fbl::unique_fd input_fd;
  EXPECT_EQ(ZX_OK, fdio_fd_create(h1.release(), input_fd.reset_and_get_address()));

  auto unexpected_command_callback = [](cmd::Command command) {
    EXPECT_TRUE(false) << "OnConsoleCommand called unexpectedly";
    return ZX_ERR_BAD_STATE;
  };
  auto unexpected_interrupt_callback = []() {
    EXPECT_TRUE(false) << "OnConsoleInterrupt called unexpectedly";
  };
  auto unexpected_error_callback = [](zx_status_t status) {
    EXPECT_TRUE(false) << "OnConsoleError called unexpectedly; status = " << status << " ("
                       << zx_status_get_string(status) << ")";
  };
  auto unexpected_autocomplete_callback = [](cmd::Autocomplete* autocomplete) {
    EXPECT_TRUE(false) << "OnConsoleAutocomplete called unexpectedly";
  };

  CallbackClient client;
  client.console_command_callback = unexpected_command_callback;
  client.console_interrupt_callback = unexpected_interrupt_callback;
  client.console_error_callback = unexpected_error_callback;
  client.console_autocomplete_callback = unexpected_autocomplete_callback;

  cmd::Console console(&client, dispatcher(), input_fd.get());
  console.Init("test> ");
  console.GetNextCommand();

  const char* input = "command1 arg0 arg1\ncommand2 xxx yyy zzz\ncommand3";
  size_t actual = 0;
  EXPECT_EQ(ZX_OK, h0.write(0, input, strlen(input), &actual));
  EXPECT_EQ(strlen(input), actual);

  int command_count = 0;
  client.console_command_callback = [&command_count](cmd::Command command) {
    command_count++;
    if (command_count == 1) {
      EXPECT_EQ(3u, command.args().size());
      EXPECT_EQ("command1", command.args()[0]);
      return ZX_ERR_NEXT;
    } else {
      EXPECT_EQ(4u, command.args().size());
      EXPECT_EQ("command2", command.args()[0]);
      return ZX_ERR_ASYNC;
    }
  };

  RunLoopUntilIdle();

  EXPECT_EQ(2, command_count);

  int error_count = 0;
  client.console_command_callback = unexpected_command_callback;
  client.console_error_callback = [&error_count](zx_status_t status) {
    error_count++;
    EXPECT_EQ(ZX_ERR_PEER_CLOSED, status);
  };

  h0.reset();
  console.GetNextCommand();

  RunLoopUntilIdle();

  EXPECT_EQ(1, error_count);
}

static zx_status_t open_client(int fd, uint32_t client_id, int* out_fd) {
  if (!out_fd) {
    return ZX_ERR_INVALID_ARGS;
  }

  fdio_t* io = fdio_unsafe_fd_to_io(fd);
  if (!io) {
    return ZX_ERR_INTERNAL;
  }

  zx::channel device_channel, client_channel;
  zx_status_t status = zx::channel::create(0, &device_channel, &client_channel);
  if (status != ZX_OK) {
    return status;
  }

  zx_status_t fidl_status = fuchsia_hardware_pty_DeviceOpenClient(
      fdio_unsafe_borrow_channel(io), client_id, device_channel.release(), &status);
  if (status != ZX_OK) {
    return status;
  }
  fdio_unsafe_release(io);
  if (fidl_status != ZX_OK) {
    return fidl_status;
  }
  if (status != ZX_OK) {
    return status;
  }

  status = fdio_fd_create(client_channel.release(), out_fd);
  if (status != ZX_OK) {
    return status;
  }
  return fcntl(*out_fd, F_SETFL, O_NONBLOCK);
}

TEST_F(Console, Interrupt) {
  fbl::unique_fd ps;
  {
    zx::channel local, remote;
    ASSERT_EQ(ZX_OK, zx::channel::create(0, &local, &remote));
    ASSERT_EQ(ZX_OK, fdio_service_connect("/svc/fuchsia.hardware.pty.Device", remote.release()));
    int fd;
    ASSERT_EQ(ZX_OK, fdio_fd_create(local.release(), &fd));
    ps.reset(fd);
    ASSERT_TRUE(ps.is_valid());
    int flags = fcntl(ps.get(), F_GETFL);
    ASSERT_LE(0, flags);
    ASSERT_EQ(0, fcntl(ps.get(), F_SETFL, flags | O_NONBLOCK));
  }

  int pc_fd;
  ASSERT_EQ(ZX_OK, open_client(ps.get(), 0, &pc_fd));
  ASSERT_LE(0, pc_fd);

  fbl::unique_fd pc(pc_fd);
  ASSERT_EQ(true, bool(pc));

  auto unexpected_command_callback = [](cmd::Command command) {
    EXPECT_TRUE(false) << "OnConsoleCommand called unexpectedly";
    return ZX_ERR_BAD_STATE;
  };
  auto unexpected_interrupt_callback = []() {
    EXPECT_TRUE(false) << "OnConsoleInterrupt called unexpectedly";
  };
  auto unexpected_error_callback = [](zx_status_t status) {
    EXPECT_TRUE(false) << "OnConsoleError called unexpectedly; status = " << status << " ("
                       << zx_status_get_string(status) << ")";
  };
  auto unexpected_autocomplete_callback = [](cmd::Autocomplete* autocomplete) {
    EXPECT_TRUE(false) << "OnConsoleAutocomplete called unexpectedly";
  };

  CallbackClient client;
  client.console_command_callback = unexpected_command_callback;
  client.console_interrupt_callback = unexpected_interrupt_callback;
  client.console_error_callback = unexpected_error_callback;
  client.console_autocomplete_callback = unexpected_autocomplete_callback;

  cmd::Console console(&client, dispatcher(), pc.get());
  console.Init("test> ");
  console.GetNextCommand();

  ASSERT_EQ(write(ps.get(), "xyzzy", 5), 5);
  ASSERT_EQ(fdio_wait_fd(pc.get(), POLLIN, nullptr, ZX_TIME_INFINITE), ZX_OK);

  RunLoopUntilIdle();

  ASSERT_EQ(write(ps.get(), "\x3", 1), 1);
  ASSERT_EQ(fdio_wait_fd(pc.get(), POLLPRI, nullptr, ZX_TIME_INFINITE), ZX_OK);

  RunLoopUntilIdle();

  int command_count = 0;
  client.console_command_callback = [&command_count](cmd::Command command) {
    command_count++;
    return ZX_ERR_ASYNC;
  };

  ASSERT_EQ(write(ps.get(), "abc\n", 4), 4);
  ASSERT_EQ(fdio_wait_fd(pc.get(), POLLIN, nullptr, ZX_TIME_INFINITE), ZX_OK);

  RunLoopUntilIdle();

  ASSERT_EQ(1, command_count);

  int interrupt_count = 0;
  client.console_interrupt_callback = [&interrupt_count]() { interrupt_count++; };

  ASSERT_EQ(write(ps.get(), "\x3", 1), 1);
  ASSERT_EQ(fdio_wait_fd(pc.get(), POLLPRI, nullptr, ZX_TIME_INFINITE), ZX_OK);

  RunLoopUntilIdle();

  ASSERT_EQ(1, interrupt_count);
}

}  // namespace
