// 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 <fidl/fuchsia.hardware.pty/cpp/wire.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/sync/completion.h>
#include <lib/zx/time.h>

#include <algorithm>
#include <iterator>

#include <zxtest/zxtest.h>

#include "pty-server-vnode.h"
#include "pty-server.h"
#include "src/lib/storage/vfs/cpp/managed_vfs.h"
#include "src/lib/storage/vfs/cpp/vfs_types.h"

namespace {

using Device = fuchsia_hardware_pty::Device;
using Connection = fidl::WireSyncClient<Device>;

class PtyTestCase : public zxtest::Test {
 public:
  PtyTestCase() : loop_(&kAsyncLoopConfigNoAttachToCurrentThread), vfs_(loop_.dispatcher()) {}

  void SetUp() override {
    ASSERT_OK(loop_.StartThread("pty-test"));
    ASSERT_NO_FATAL_FAILURE(CreateNewServer(server_));
  }
  void TearDown() override {
    sync_completion_t completion;
    vfs_.Shutdown([&completion](zx_status_t) { sync_completion_signal(&completion); });
    ASSERT_OK(sync_completion_wait_deadline(&completion, zx::time::infinite().get()));
  }

 protected:
  static zx::status<Connection> OpenClient(Connection& conn, uint32_t id) {
    auto endpoints = fidl::CreateEndpoints<Device>();
    if (endpoints.is_error()) {
      return endpoints.take_error();
    }
    fidl::WireResult result = conn->OpenClient(id, std::move(endpoints->server));
    if (result.status() != ZX_OK) {
      return zx::error(ZX_ERR_BAD_STATE);
    }
    if (result->s != ZX_OK) {
      return zx::error(result->s);
    }
    return zx::ok(Connection(std::move(endpoints->client)));
  }

  async_dispatcher_t* dispatcher() { return loop_.dispatcher(); }
  fs::ManagedVfs* vfs() { return &vfs_; }
  Connection take_server() { return std::move(server_); }

 private:
  void CreateNewServer(Connection& conn) {
    fbl::RefPtr<PtyServer> server;
    ASSERT_OK(PtyServer::Create(&server, &vfs_));
    auto vnode = fbl::MakeRefCounted<PtyServerVnode>(std::move(server));

    auto endpoints = fidl::CreateEndpoints<Device>();
    ASSERT_OK(endpoints.status_value());
    ASSERT_OK(vfs()->Serve(std::move(vnode), endpoints->server.TakeChannel(),
                           fs::VnodeConnectionOptions::ReadWrite()));
    conn = Connection(std::move(endpoints->client));
  }

  async::Loop loop_;
  fs::ManagedVfs vfs_;
  Connection server_;
};

zx::eventpair GetEvent(Connection& conn) {
  auto result = conn->Describe();
  if (result.status() != ZX_OK) {
    return {};
  }
  zx::eventpair event = std::move(result->info.tty().event);
  return event;
}

void WriteCtrlC(Connection& conn) {
  uint8_t data[] = {0x03};
  const fidl::WireResult result = conn->Write(fidl::VectorView<uint8_t>::FromExternal(data));
  ASSERT_OK(result.status());
  const fitx::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  ASSERT_EQ(response.value()->actual_count, std::size(data));
}

// Make sure the server connections describe appropriately
TEST_F(PtyTestCase, ServerDescribe) {
  Connection server{take_server()};
  auto result = server->Describe();
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->info.is_tty());
  ASSERT_TRUE(result->info.tty().event.is_valid());
}  // namespace

TEST_F(PtyTestCase, ServerSetWindowSize) {
  Connection server{take_server()};
  auto result = server->SetWindowSize({.width = 80, .height = 24});
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
}  // namespace

TEST_F(PtyTestCase, ServerClrSetFeature) {
  Connection server{take_server()};
  auto result = server->ClrSetFeature(0, 0);
  ASSERT_OK(result.status());
  // ClrSetFeature is only meaningful on clients
  ASSERT_STATUS(result->status, ZX_ERR_NOT_SUPPORTED);
}

TEST_F(PtyTestCase, ServerGetWindowSize) {
  Connection server{take_server()};
  auto result = server->GetWindowSize();
  ASSERT_OK(result.status());
  // Our original implementation didn't support this, so preserve that behavior.
  // It's not clear why, though.  If this is causing problems, we should
  // probably just implement it.
  ASSERT_STATUS(result->status, ZX_ERR_NOT_SUPPORTED);
}

TEST_F(PtyTestCase, ServerMakeActive) {
  Connection server{take_server()};
  auto result = server->MakeActive(0);
  ASSERT_OK(result.status());
  // MakeActive is only meaningful on clients
  ASSERT_STATUS(result->status, ZX_ERR_NOT_SUPPORTED);
}

TEST_F(PtyTestCase, ServerReadEvents) {
  Connection server{take_server()};
  auto result = server->ReadEvents();
  ASSERT_OK(result.status());
  // ReadEvents is only meaningful on clients
  ASSERT_STATUS(result->status, ZX_ERR_NOT_SUPPORTED);
}

// Basic test of opening a client
TEST_F(PtyTestCase, ServerBasicOpenClient) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());

  // Make sure our client connection is valid after this
  ASSERT_STATUS(
      client.value().client_end().channel().wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);
}

// Try opening two clients with the same id
TEST_F(PtyTestCase, ServerOpenClientTwice) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());
  ASSERT_STATUS(OpenClient(server, 0).status_value(), ZX_ERR_INVALID_ARGS);

  // Our original client connection should still be good.
  ASSERT_STATUS(
      client.value().client_end().channel().wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);
}

// Try opening two clients with different ids
TEST_F(PtyTestCase, ServerOpenClientTwoDifferent) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());
  zx::status client2 = OpenClient(server, 0);
  ASSERT_OK(client2.status_value());

  // Both connections should be good
  ASSERT_STATUS(
      client.value().client_end().channel().wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);
  ASSERT_STATUS(
      client2.value().client_end().channel().wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);
}

// Verify a server with no clients behaves as expected
TEST_F(PtyTestCase, ServerWithNoClientsInitialConditions) {
  Connection server{take_server()};
  zx::eventpair event = GetEvent(server);

  auto check_state = [&]() {
    zx_signals_t observed = 0;
    ASSERT_STATUS(event.wait_one(0, zx::time{}, &observed), ZX_ERR_TIMED_OUT);
    // Precisely this set of signals should be asserted
    ASSERT_EQ(observed, static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable |
                                                  fuchsia_device::wire::DeviceSignal::kHangup));

    // Attempts to read should get 0 bytes and ZX_OK
    {
      const fidl::WireResult result = server->Read(10);
      ASSERT_OK(result.status());
      const fitx::result response = result.value();
      ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
      const fidl::VectorView data = response.value()->data;
      ASSERT_EQ(std::string_view(reinterpret_cast<const char*>(data.data()), data.count()),
                std::string_view());
    }

    // Attempts to write should fail with ZX_ERR_PEER_CLOSED
    {
      uint8_t data[16] = {};
      const fidl::WireResult result = server->Write(fidl::VectorView<uint8_t>::FromExternal(data));
      ASSERT_OK(result.status());
      const fitx::result response = result.value();
      ASSERT_TRUE(response.is_error());
      ASSERT_STATUS(response.error_value(), ZX_ERR_PEER_CLOSED);
    }
  };

  ASSERT_NO_FATAL_FAILURE(check_state());

  // Create a client and close it, then make sure we're back in the initial
  // state
  {
    zx::status client = OpenClient(server, 1);
    ASSERT_OK(client.status_value());
  }
  // Wait for the server to signal that it got the client disconnect
  ASSERT_OK(event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kHangup),
                           zx::time::infinite(), nullptr));

  ASSERT_NO_FATAL_FAILURE(check_state());
}

// Verify a server with a client has the right state
TEST_F(PtyTestCase, ServerWithClientInitialConditions) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());

  zx::eventpair server_event = GetEvent(server);
  zx::eventpair client_event = GetEvent(client.value());

  zx_signals_t observed = 0;
  ASSERT_STATUS(server_event.wait_one(0, zx::time{}, &observed), ZX_ERR_TIMED_OUT);
  ASSERT_EQ(observed, static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kWritable));

  observed = 0;
  ASSERT_STATUS(client_event.wait_one(0, zx::time{}, &observed), ZX_ERR_TIMED_OUT);
  ASSERT_EQ(observed, static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kWritable));

  // Attempts to read on either side should get SHOULD_WAIT
  {
    const fidl::WireResult result = server->Read(10);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_error());
    ASSERT_STATUS(response.error_value(), ZX_ERR_SHOULD_WAIT);
  }
  {
    const fidl::WireResult result = client->Read(10);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_error());
    ASSERT_STATUS(response.error_value(), ZX_ERR_SHOULD_WAIT);
  }

  // Client should be in cooked mode
  {
    auto result = client->ClrSetFeature(0, 0);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->features, 0);
  }
}

// Verify a read from a server for 0 bytes doesn't return ZX_ERR_SHOULD_WAIT
TEST_F(PtyTestCase, ServerEmpty0ByteRead) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());

  const fidl::WireResult result = server->Read(0);
  ASSERT_OK(result.status());
  const fitx::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  const fidl::VectorView data = response.value()->data;
  ASSERT_EQ(std::string_view(reinterpret_cast<const char*>(data.data()), data.count()),
            std::string_view());
}

// Verify a write by the server for 0 bytes when the receiving client is full doesn't return
// ZX_ERR_SHOULD_WAIT
TEST_F(PtyTestCase, ClientFull0ByteServerWrite) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());

  // Fill up FIFO
  while (true) {
    uint8_t buf[256] = {};
    const fidl::WireResult result = server->Write(fidl::VectorView<uint8_t>::FromExternal(buf));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    if (response.is_error()) {
      ASSERT_STATUS(response.error_value(), ZX_ERR_SHOULD_WAIT);
      break;
    }
    ASSERT_GT(response.value()->actual_count, 0);
  }

  const fidl::WireResult result = server->Write({});
  ASSERT_OK(result.status());
  const fitx::result response = result.value();
  ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
  ASSERT_EQ(response.value()->actual_count, 0);
}

// Verify a write by a client for 0 bytes when the client isn't active returns
// ZX_ERR_SHOULD_WAIT
TEST_F(PtyTestCase, ClientInactive0ByteClientWrite) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());
  zx::status inactive_client = OpenClient(server, 0);
  ASSERT_OK(inactive_client.status_value());

  const fidl::WireResult result = inactive_client->Write({});
  ASSERT_OK(result.status());
  const fitx::result response = result.value();
  ASSERT_TRUE(response.is_error());
  ASSERT_STATUS(response.error_value(), ZX_ERR_SHOULD_WAIT);
}

// Make sure the client connections describe appropriately
TEST_F(PtyTestCase, ClientDescribe) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());

  auto result = client->Describe();
  ASSERT_OK(result.status());
  ASSERT_TRUE(result->info.is_tty());
  ASSERT_TRUE(result->info.tty().event.is_valid());
}

TEST_F(PtyTestCase, ClientWindowSize) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());

  {
    auto result = server->SetWindowSize({.width = 80, .height = 24});
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }
  {
    auto result = client->GetWindowSize();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->size.width, 80);
    ASSERT_EQ(result->size.height, 24);
  }
  {
    auto result = client->SetWindowSize({.width = 5, .height = 32});
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }
  {
    auto result = client->GetWindowSize();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->size.width, 5);
    ASSERT_EQ(result->size.height, 32);
  }
}

TEST_F(PtyTestCase, ClientClrSetFeature) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());

  {
    auto result = client->ClrSetFeature(0, 0);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->features, 0);
  }

  // Make sure we can set bits
  {
    auto result = client->ClrSetFeature(0, fuchsia_hardware_pty::wire::kFeatureRaw);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->features, fuchsia_hardware_pty::wire::kFeatureRaw);
  }

  // If we don't change any bits, we should see the new settings
  {
    auto result = client->ClrSetFeature(0, 0);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->features, fuchsia_hardware_pty::wire::kFeatureRaw);
  }

  // Make sure we can clear bits
  {
    auto result = client->ClrSetFeature(fuchsia_hardware_pty::wire::kFeatureRaw, 0);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->features, 0);
  }
}

TEST_F(PtyTestCase, ClientClrSetFeatureInvalidBit) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());

  {
    auto result = client->ClrSetFeature(0, 0x2);
    ASSERT_OK(result.status());
    ASSERT_STATUS(result->status, ZX_ERR_NOT_SUPPORTED);
    ASSERT_EQ(result->features, 0);
  }

  {
    auto result = client->ClrSetFeature(0x2, 0);
    ASSERT_OK(result.status());
    ASSERT_STATUS(result->status, ZX_ERR_NOT_SUPPORTED);
    ASSERT_EQ(result->features, 0);
  }
}

TEST_F(PtyTestCase, ClientGetWindowSizeServerNeverSet) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());

  auto result = client->GetWindowSize();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  ASSERT_EQ(result->size.width, 0);
  ASSERT_EQ(result->size.height, 0);
}

// Each client should have its own feature flags
TEST_F(PtyTestCase, ClientIndependentFeatureFlags) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());
  zx::status client2 = OpenClient(server, 0);
  ASSERT_OK(client2.status_value());

  {
    auto result = client->ClrSetFeature(0, fuchsia_hardware_pty::wire::kFeatureRaw);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->features, fuchsia_hardware_pty::wire::kFeatureRaw);
  }

  {
    // Client 2 shouldn't see the changes
    auto result = client2->ClrSetFeature(0, 0);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->features, 0);
  }
}

TEST_F(PtyTestCase, ClientMakeActive) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());
  zx::status client2 = OpenClient(server, 0);
  ASSERT_OK(client2.status_value());

  {
    auto result = client->MakeActive(0);
    ASSERT_OK(result.status());
    // This client is not the controlling client (id=0), so it cannot change the
    // active client
    ASSERT_STATUS(result->status, ZX_ERR_ACCESS_DENIED);
  }
  {
    auto result = client2->MakeActive(1);
    ASSERT_OK(result.status());
    // This client is the controlling client (id=0), so it can.
    ASSERT_OK(result->status);
  }
  {
    // Changing the active client to the existing active client should be fine
    auto result = client2->MakeActive(1);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }
  {
    // Changing the active client to the control client should be fine
    auto result = client2->MakeActive(0);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }
  {
    // Changing the active client to a non-existent client should fail
    auto result = client2->MakeActive(2);
    ASSERT_OK(result.status());
    ASSERT_STATUS(result->status, ZX_ERR_NOT_FOUND);
  }
}

TEST_F(PtyTestCase, ClientReadEvents) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());
  zx::status client2 = OpenClient(server, 0);
  ASSERT_OK(client2.status_value());

  {
    auto result = client->ReadEvents();
    ASSERT_OK(result.status());
    // This client is not the controlling client (id=0), so it cannot read events
    ASSERT_STATUS(result->status, ZX_ERR_ACCESS_DENIED);
  }

  {
    auto result = client2->ReadEvents();
    ASSERT_OK(result.status());
    // This client is the controlling client (id=0), so it can read events
    ASSERT_OK(result->status);
    ASSERT_EQ(result->events, 0);
  }
}

// Reading events should clear the event condition
TEST_F(PtyTestCase, ClientReadEventsClears) {
  Connection server{take_server()};
  zx::status active_client = OpenClient(server, 1);
  ASSERT_OK(active_client.status_value());
  zx::status control_client = OpenClient(server, 0);
  ASSERT_OK(control_client.status_value());

  zx::eventpair control_event = GetEvent(control_client.value());

  // No events yet
  ASSERT_STATUS(
      control_event.wait_one(static_cast<zx_signals_t>(fuchsia_hardware_pty::wire::kSignalEvent),
                             zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);

  // Write a ^C byte from the server to trigger a cooked-mode event
  ASSERT_NO_FATAL_FAILURE(WriteCtrlC(server));

  ASSERT_OK(
      control_event.wait_one(static_cast<zx_signals_t>(fuchsia_hardware_pty::wire::kSignalEvent),
                             zx::time::infinite(), nullptr));

  {
    auto result = control_client->ReadEvents();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->events, fuchsia_hardware_pty::wire::kEventInterrupt);
  }

  // Signal should have cleared
  ASSERT_STATUS(
      control_event.wait_one(static_cast<zx_signals_t>(fuchsia_hardware_pty::wire::kSignalEvent),
                             zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);

  // Event should have cleared
  {
    auto result = control_client->ReadEvents();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->events, 0);
  }
}

// Events arrive even without a controlling client connected
TEST_F(PtyTestCase, EventsSentWithNoControllingClient) {
  Connection server{take_server()};
  zx::status active_client = OpenClient(server, 1);
  ASSERT_OK(active_client.status_value());

  // Write a ^C byte from the server to trigger a cooked-mode event
  ASSERT_NO_FATAL_FAILURE(WriteCtrlC(server));

  // Connect a control client to inspect the event
  zx::status control_client = OpenClient(server, 0);
  ASSERT_OK(control_client.status_value());

  zx::eventpair control_event = GetEvent(control_client.value());
  ASSERT_OK(control_event.wait_one(
      static_cast<zx_signals_t>(fuchsia_hardware_pty::wire::kSignalEvent), zx::time{}, nullptr));

  {
    auto result = control_client->ReadEvents();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->events, fuchsia_hardware_pty::wire::kEventInterrupt);
  }
}

TEST_F(PtyTestCase, SetWindowSizeSendsEvent) {
  Connection server{take_server()};
  zx::status control_client = OpenClient(server, 0);
  ASSERT_OK(control_client.status_value());

  zx::eventpair control_event = GetEvent(control_client.value());

  // No events yet
  ASSERT_STATUS(control_event.wait_one(static_cast<zx_signals_t>(static_cast<zx_signals_t>(
                                           fuchsia_hardware_pty::wire::kSignalEvent)),
                                       zx::time{}, nullptr),
                ZX_ERR_TIMED_OUT);
  {
    auto result = control_client->ReadEvents();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->events, 0);
  }

  // SetWindowSize which should trigger an event
  {
    auto result = server->SetWindowSize({.width = 123, .height = 45});
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }

  ASSERT_OK(
      control_event.wait_one(static_cast<zx_signals_t>(fuchsia_hardware_pty::wire::kSignalEvent),
                             zx::time::infinite(), nullptr));
  {
    auto result = control_client->ReadEvents();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->events, fuchsia_hardware_pty::wire::kEventWindowSize);
  }
}

TEST_F(PtyTestCase, NonControllingClientOpenClient) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());

  // This client is not the controlling client (id=0), so it cannot create new
  // clients
  ASSERT_STATUS(OpenClient(client.value(), 2).status_value(), ZX_ERR_ACCESS_DENIED);
}

TEST_F(PtyTestCase, ControllingClientOpenClient) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());

  zx::status client2 = OpenClient(client.value(), 1);
  ASSERT_OK(client2.status_value());
}

TEST_F(PtyTestCase, ActiveClientCloses) {
  Connection server{take_server()};
  zx::status control_client = OpenClient(server, 0);
  ASSERT_OK(control_client.status_value());
  {
    zx::status active_client = OpenClient(server, 1);
    ASSERT_OK(active_client.status_value());
    auto result = control_client->MakeActive(1);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }

  zx::eventpair control_event = GetEvent(control_client.value());
  zx_signals_t observed = 0;
  ASSERT_OK(
      control_event.wait_one(static_cast<zx_signals_t>(fuchsia_hardware_pty::wire::kSignalEvent),
                             zx::time::infinite(), &observed));
  // Wait again with no timeout, so that observed doesn't have any transient
  // signals in it.
  ASSERT_OK(
      control_event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kHangup),
                             zx::time{}, &observed));
  ASSERT_EQ(observed, static_cast<zx_signals_t>(fuchsia_hardware_pty::wire::kSignalEvent |
                                                fuchsia_device::wire::DeviceSignal::kHangup));

  auto result = control_client->ReadEvents();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  ASSERT_EQ(result->events, fuchsia_hardware_pty::wire::kEventHangup);
}

// Makes sure nothing goes wrong when the active client is the controling
// client and it closes.
TEST_F(PtyTestCase, ActiveClientClosesWhenControl) {
  Connection server{take_server()};
  {
    zx::status control_client = OpenClient(server, 0);
    ASSERT_OK(control_client.status_value());
  }
  zx::eventpair event = GetEvent(server);
  zx_signals_t observed = 0;
  ASSERT_OK(event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kHangup),
                           zx::time::infinite(), &observed));
}

TEST_F(PtyTestCase, ServerClosesWhenClientPresent) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 0);
  ASSERT_OK(client.status_value());

  // Write some data to the client, so we can verify the client can drain the
  // buffer still.

  uint8_t kTestData[] = "hello world";
  {
    const fidl::WireResult result =
        server->Write(fidl::VectorView<uint8_t>::FromExternal(kTestData));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    ASSERT_EQ(response.value()->actual_count, std::size(kTestData));
  }

  server = {};

  zx::eventpair event = GetEvent(client.value());
  zx_signals_t observed = 0;
  ASSERT_OK(event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kHangup),
                           zx::time::infinite(), &observed));
  // Wait again with no timeout, so that observed doesn't have any transient
  // signals in it.
  ASSERT_OK(event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kHangup),
                           zx::time{}, &observed));
  ASSERT_EQ(observed, static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kHangup |
                                                fuchsia_device::wire::DeviceSignal::kReadable));

  {
    auto result = client->ReadEvents();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->events, fuchsia_hardware_pty::wire::kEventHangup);
  }

  // Attempts to drain the buffer should succeed
  {
    // Request more bytes than are present
    const fidl::WireResult result = client->Read(std::size(kTestData) + 10);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fidl::VectorView data = response.value()->data;
    ASSERT_EQ(std::string_view(reinterpret_cast<const char*>(data.data()), data.count()),
              std::string_view(reinterpret_cast<char*>(kTestData), std::size(kTestData)));
  }

  // Attempts to read the empty buffer should fail with ZX_ERR_PEER_CLOSED
  {
    const fidl::WireResult result = client->Read(10);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_error());
    ASSERT_STATUS(response.error_value(), ZX_ERR_PEER_CLOSED);
  }

  // Attempts to write should fail with ZX_ERR_PEER_CLOSED
  {
    uint8_t data[16] = {};
    const fidl::WireResult result = client->Write(fidl::VectorView<uint8_t>::FromExternal(data));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_error());
    ASSERT_STATUS(response.error_value(), ZX_ERR_PEER_CLOSED);
  }
}

// Test writes from the client to the server when the client is cooked
TEST_F(PtyTestCase, ServerReadClientCooked) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());

  // In cooked mode, client writes should have \n transformed to \r\n, and
  // control chars untouched.
  uint8_t kTestData[] = "hello\x03 world\ntest message\n";
  const uint8_t kExpectedReadback[] = "hello\x03 world\r\ntest message\r\n";
  {
    const fidl::WireResult result =
        client->Write(fidl::VectorView<uint8_t>::FromExternal(kTestData));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    ASSERT_EQ(response.value()->actual_count, std::size(kTestData));
  }

  zx::eventpair event = GetEvent(server);
  ASSERT_OK(event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                           zx::time::infinite(), nullptr));
  {
    const fidl::WireResult result = server->Read(std::size(kExpectedReadback) + 10);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fidl::VectorView data = response.value()->data;
    ASSERT_EQ(std::string_view(reinterpret_cast<const char*>(data.data()), data.count()),
              std::string_view(reinterpret_cast<const char*>(kExpectedReadback),
                               std::size(kExpectedReadback)));
  }
  // Nothing left to read
  ASSERT_STATUS(
      event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                     zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);
}

// Test writes from the server to the client when the client is cooked
TEST_F(PtyTestCase, ServerWriteClientCooked) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());

  // In cooked mode, server writes should have newlines untouched and control
  // chars should cause a short write
  uint8_t kTestData[] = "hello world\ntest\x03 message\n";
  // We expect to read this back, but without the trailing nul
  const uint8_t kExpectedReadbackWithNul[] = "hello world\ntest";
  {
    const fidl::WireResult result =
        server->Write(fidl::VectorView<uint8_t>::FromExternal(kTestData));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    // We expect to see the written count to include the ^C
    ASSERT_EQ(response.value()->actual_count, std::size(kExpectedReadbackWithNul) - 1 + 1);
  }

  zx::eventpair event = GetEvent(client.value());
  ASSERT_OK(event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                           zx::time::infinite(), nullptr));
  {
    const fidl::WireResult result = client->Read(std::size(kExpectedReadbackWithNul) + 10);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fidl::VectorView data = response.value()->data;
    ASSERT_EQ(std::string_view(reinterpret_cast<const char*>(data.data()), data.count()),
              std::string_view(reinterpret_cast<const char*>(kExpectedReadbackWithNul),
                               std::size(kExpectedReadbackWithNul) - 1));
  }
  // Nothing left to read
  ASSERT_STATUS(
      event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                     zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);
}

// Test writes from the client to the server when the client is raw
TEST_F(PtyTestCase, ServerReadClientRaw) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());

  {
    auto result = client->ClrSetFeature(0, fuchsia_hardware_pty::wire::kFeatureRaw);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }

  // In raw mode, client writes should be untouched.
  uint8_t kTestData[] = "hello\x03 world\ntest message\n";
  {
    const fidl::WireResult result =
        client->Write(fidl::VectorView<uint8_t>::FromExternal(kTestData));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    ASSERT_EQ(response.value()->actual_count, std::size(kTestData));
  }

  zx::eventpair event = GetEvent(server);
  ASSERT_OK(event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                           zx::time::infinite(), nullptr));
  {
    const fidl::WireResult result = server->Read(std::size(kTestData) + 10);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fidl::VectorView data = response.value()->data;
    ASSERT_EQ(std::string_view(reinterpret_cast<const char*>(data.data()), data.count()),
              std::string_view(reinterpret_cast<char*>(kTestData), std::size(kTestData)));
  }
  // Nothing left to read
  ASSERT_STATUS(
      event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                     zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);
}

// Test writes from the server to the client when the client is raw
TEST_F(PtyTestCase, ServerWriteClientRaw) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());
  zx::status control_client = OpenClient(server, 0);
  ASSERT_OK(control_client.status_value());

  {
    auto result = client->ClrSetFeature(0, fuchsia_hardware_pty::wire::kFeatureRaw);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }

  // In raw mode, server writes should be untouched.
  uint8_t kTestData[] = "hello world\ntest\x03 message\n";
  {
    const fidl::WireResult result =
        server->Write(fidl::VectorView<uint8_t>::FromExternal(kTestData));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    ASSERT_EQ(response.value()->actual_count, std::size(kTestData));
  }

  zx::eventpair event = GetEvent(client.value());
  ASSERT_OK(event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                           zx::time::infinite(), nullptr));
  {
    const fidl::WireResult result = client->Read(std::size(kTestData) + 10);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fidl::VectorView data = response.value()->data;
    ASSERT_EQ(std::string_view(reinterpret_cast<const char*>(data.data()), data.count()),
              std::string_view(reinterpret_cast<char*>(kTestData), std::size(kTestData)));
  }
  // Nothing left to read
  ASSERT_STATUS(
      event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                     zx::time{}, nullptr),
      ZX_ERR_TIMED_OUT);

  // Make sure we didn't see an INTERRUPT_EVENT.
  {
    auto result = control_client->ReadEvents();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    ASSERT_EQ(result->events, 0);
  }
}

TEST_F(PtyTestCase, ServerFillsClientFifo) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());

  zx::eventpair server_event = GetEvent(server);
  zx::eventpair client_event = GetEvent(client.value());

  uint8_t kTestString[] = "abcdefghijklmnopqrstuvwxyz";
  size_t total_written = 0;
  while (server_event.wait_one(
             static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kWritable), zx::time{},
             nullptr) == ZX_OK) {
    const fidl::WireResult result = server->Write(
        fidl::VectorView<uint8_t>::FromExternal(kTestString, std::size(kTestString) - 1));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    ASSERT_GT(response.value()->actual_count, 0);
    total_written += response.value()->actual_count;
  }

  // Trying to write when full gets SHOULD_WAIT
  {
    const fidl::WireResult result = server->Write(
        fidl::VectorView<uint8_t>::FromExternal(kTestString, std::size(kTestString) - 1));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_error());
    ASSERT_STATUS(response.error_value(), ZX_ERR_SHOULD_WAIT);
  }

  // Client can read FIFO contents back out
  size_t total_read = 0;
  while (total_read < total_written) {
    ASSERT_OK(client_event.wait_one(
        static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable), zx::time{},
        nullptr));
    const fidl::WireResult result = client->Read(std::size(kTestString) - 1);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fidl::VectorView data = response.value()->data;
    ASSERT_EQ(data.count(), std::min(std::size(kTestString) - 1, total_written - total_read));
    ASSERT_EQ(std::string_view(reinterpret_cast<const char*>(data.data()), data.count()),
              std::string_view(reinterpret_cast<char*>(kTestString), data.count()));
    total_read += data.count();
  }

  ASSERT_STATUS(client_event.wait_one(
                    static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                    zx::time{}, nullptr),
                ZX_ERR_TIMED_OUT);
}

TEST_F(PtyTestCase, ClientFillsServerFifo) {
  Connection server{take_server()};
  zx::status client = OpenClient(server, 1);
  ASSERT_OK(client.status_value());

  zx::eventpair server_event = GetEvent(server);
  zx::eventpair client_event = GetEvent(client.value());

  uint8_t kTestString[] = "abcdefghijklmnopqrstuvwxyz";
  size_t total_written = 0;
  while (client_event.wait_one(
             static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kWritable), zx::time{},
             nullptr) == ZX_OK) {
    const fidl::WireResult result = client->Write(
        fidl::VectorView<uint8_t>::FromExternal(kTestString, std::size(kTestString) - 1));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    ASSERT_GT(response.value()->actual_count, 0);
    total_written += response.value()->actual_count;
  }

  // Trying to write when full gets SHOULD_WAIT
  {
    const fidl::WireResult result = client->Write(
        fidl::VectorView<uint8_t>::FromExternal(kTestString, std::size(kTestString) - 1));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_error());
    ASSERT_STATUS(response.error_value(), ZX_ERR_SHOULD_WAIT);
  }

  // Server can read FIFO contents back out
  size_t total_read = 0;
  while (total_read < total_written) {
    ASSERT_OK(server_event.wait_one(
        static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable), zx::time{},
        nullptr));
    const fidl::WireResult result = server->Read(std::size(kTestString) - 1);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fidl::VectorView data = response.value()->data;
    ASSERT_EQ(data.count(), std::min(std::size(kTestString) - 1, total_written - total_read));
    ASSERT_EQ(std::string_view(reinterpret_cast<const char*>(data.data()), data.count()),
              std::string_view(reinterpret_cast<char*>(kTestString), data.count()));
    total_read += data.count();
  }

  ASSERT_STATUS(server_event.wait_one(
                    static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                    zx::time{}, nullptr),
                ZX_ERR_TIMED_OUT);
}

TEST_F(PtyTestCase, NonActiveClientsCantWrite) {
  Connection server{take_server()};
  zx::status control_client = OpenClient(server, 0);
  ASSERT_OK(control_client.status_value());
  zx::status other_client = OpenClient(server, 1);
  ASSERT_OK(other_client.status_value());

  // control_client is the current active

  zx::eventpair event = GetEvent(other_client.value());
  zx_signals_t observed = 0;
  ASSERT_STATUS(event.wait_one(0, zx::time{}, &observed), ZX_ERR_TIMED_OUT);
  ASSERT_FALSE(observed & static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kWritable));
  {
    uint8_t byte = 0;
    const fidl::WireResult result =
        other_client->Write(fidl::VectorView<uint8_t>::FromExternal(&byte, 1));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_error());
    ASSERT_STATUS(response.error_value(), ZX_ERR_SHOULD_WAIT);
  }
}

TEST_F(PtyTestCase, ClientsHaveIndependentFifos) {
  Connection server{take_server()};
  zx::status control_client = OpenClient(server, 0);
  ASSERT_OK(control_client.status_value());
  zx::status other_client = OpenClient(server, 1);
  ASSERT_OK(other_client.status_value());

  uint8_t kControlClientByte = 1;
  uint8_t kOtherClientByte = 2;

  // control_client is the current active, so it should go to its FIFO
  {
    const fidl::WireResult result =
        server->Write(fidl::VectorView<uint8_t>::FromExternal(&kControlClientByte, 1));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    ASSERT_EQ(response.value()->actual_count, 1);
  }

  // Switch active clients
  {
    auto result = control_client->MakeActive(1);
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
  }

  // This should go to the other client's FIFO
  {
    const fidl::WireResult result =
        server->Write(fidl::VectorView<uint8_t>::FromExternal(&kOtherClientByte, 1));
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    ASSERT_EQ(response.value()->actual_count, 1);
  }

  auto check_client = [&](Connection& client, uint8_t expected_value) {
    zx::eventpair event = GetEvent(client);

    ASSERT_OK(
        event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                       zx::time{}, nullptr));

    const fidl::WireResult result = client->Read(10);
    ASSERT_OK(result.status());
    const fitx::result response = result.value();
    ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value()));
    const fidl::VectorView data = response.value()->data;
    ASSERT_EQ(data.count(), 1);
    ASSERT_EQ(data.data()[0], expected_value);

    ASSERT_STATUS(
        event.wait_one(static_cast<zx_signals_t>(fuchsia_device::wire::DeviceSignal::kReadable),
                       zx::time{}, nullptr),
        ZX_ERR_TIMED_OUT);
  };

  ASSERT_NO_FATAL_FAILURE(check_client(other_client.value(), kOtherClientByte));
  ASSERT_NO_FATAL_FAILURE(check_client(control_client.value(), kControlClientByte));
}

}  // namespace
