// Copyright 2018 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 <gmock/gmock.h>
#include <gtest/gtest.h>
#include <string.h>

#include <future>

#include "guest_test.h"

template <class T>
class VsockGuestTest : public GuestTest<T>, public fuchsia::virtualization::HostVsockAcceptor {
 public:
  struct IncomingRequest {
    uint32_t src_cid;
    uint32_t src_port;
    uint32_t port;
    fuchsia::virtualization::HostVsockAcceptor::AcceptCallback callback;
  };

  std::vector<IncomingRequest> requests;

  void Accept(uint32_t src_cid, uint32_t src_port, uint32_t port,
              AcceptCallback callback) override {
    requests.push_back({src_cid, src_port, port, std::move(callback)});
  }

  void Read(zx::socket& socket, size_t amount) {
    size_t total_read = 0;
    while (total_read != amount) {
      size_t read;
      char buf[1000];
      zx_signals_t pending;
      socket.wait_one(ZX_SOCKET_READABLE, zx::time::infinite(), &pending);
      ASSERT_TRUE((pending & ZX_SOCKET_READABLE) != 0);
      size_t read_amount = std::min(amount - total_read, sizeof(buf));
      ASSERT_EQ(socket.read(0, &buf, read_amount, &read), ZX_OK);
      total_read += read;
    }
  }

  void TestReadWrite(zx::socket& socket) {
    Read(socket, 60000 * 4);
    uint8_t value = 42;
    size_t actual;
    ASSERT_EQ(socket.write(0, &value, 1, &actual), ZX_OK);
    EXPECT_EQ(static_cast<int>(actual), 1);
  }

  void TestThread() {
    async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);

    fuchsia::virtualization::HostVsockEndpointSyncPtr vsock_endpoint;
    this->GetHostVsockEndpoint(vsock_endpoint.NewRequest());

    fidl::Binding<fuchsia::virtualization::HostVsockAcceptor> binding{this};
    zx_status_t out_status;
    ASSERT_EQ(vsock_endpoint->Listen(8000, binding.NewBinding(), &out_status), ZX_OK);
    ASSERT_EQ(out_status, ZX_OK);

    ASSERT_EQ(binding.WaitForMessage(), ZX_OK);
    ASSERT_TRUE(requests.size() == 1);
    ASSERT_EQ(requests[0].src_cid, this->GetGuestCid());
    ASSERT_EQ(requests[0].src_port, 49152u);
    ASSERT_EQ(requests[0].port, 8000u);

    zx::socket socket1, socket2;
    ASSERT_EQ(zx::socket::create(ZX_SOCKET_STREAM, &socket1, &socket2), ZX_OK);
    requests.back().callback(ZX_OK, std::move(socket2));
    requests.pop_back();
    TestReadWrite(socket1);

    zx_signals_t pending;
    // Read the read/write completes we expect the util to close the connection.
    socket1.wait_one(ZX_SOCKET_PEER_CLOSED, zx::time::infinite(), &pending);
    ASSERT_TRUE((pending & ZX_SOCKET_PEER_CLOSED) != 0);

    socket1.reset();

    // Attempt to connect into the guest
    EXPECT_EQ(zx::socket::create(ZX_SOCKET_STREAM, &socket1, &socket2), ZX_OK);
    ASSERT_EQ(vsock_endpoint->Connect(this->GetGuestCid(), 8001, std::move(socket2), &out_status),
              ZX_OK);
    ASSERT_EQ(out_status, ZX_OK);

    // Wait for all the data
    TestReadWrite(socket1);
    // Close the connection by dropping the socket.
    socket1.reset();

    // Open another connection.
    EXPECT_EQ(zx::socket::create(ZX_SOCKET_STREAM, &socket1, &socket2), ZX_OK);
    ASSERT_EQ(vsock_endpoint->Connect(this->GetGuestCid(), 8002, std::move(socket2), &out_status),
              ZX_OK);
    ASSERT_EQ(out_status, ZX_OK);
    // Read some data then close the connection
    Read(socket1, 10);
    socket1.reset();

    // Wait for another connection to get accepted
    EXPECT_EQ(zx::socket::create(ZX_SOCKET_STREAM, &socket1, &socket2), ZX_OK);
    ASSERT_EQ(vsock_endpoint->Connect(this->GetGuestCid(), 8003, std::move(socket2), &out_status),
              ZX_OK);
    ASSERT_EQ(out_status, ZX_OK);
    // Keep writing until we get peer closed
    zx_status_t status;
    do {
      socket1.wait_one(ZX_SOCKET_PEER_CLOSED | ZX_SOCKET_WRITABLE, zx::time::infinite(), &pending);
      if ((pending & ZX_SOCKET_WRITABLE) != 0) {
        uint8_t buf[1000] = {};
        size_t actual = 0;
        status = socket1.write(0, buf, sizeof(buf), &actual);
      }
    } while (status != ZX_ERR_PEER_CLOSED && (pending & ZX_SOCKET_PEER_CLOSED) == 0);
  }
};

using GuestTypes = ::testing::Types<ZirconEnclosedGuest, DebianEnclosedGuest>;

TYPED_TEST_SUITE(VsockGuestTest, GuestTypes);

TYPED_TEST(VsockGuestTest, DISABLED_ConnectDisconnect) {
  auto handle = std::async(std::launch::async, [this] { this->TestThread(); });

  std::string result;
  EXPECT_EQ(this->RunUtil("virtio_vsock_test_util", {}, &result), ZX_OK);

  handle.wait();

  EXPECT_THAT(result, ::testing::HasSubstr("PASS"));
}
