// Copyright 2020 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/task.h>
#include <lib/async/wait.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/fidl/llcpp/server.h>

#include <gtest/gtest.h>
#include <llcpptest/handlerights/test/llcpp/fidl.h>

namespace test = ::llcpp::llcpptest::handlerights::test;

class HandleRightsServer : public test::HandleRights::Interface {
 public:
  void SyncGetHandleWithTooFewRights(
      SyncGetHandleWithTooFewRightsCompleter::Sync& completer) override {
    zx::event ev;
    ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
    ASSERT_EQ(ZX_OK, ev.replace(ZX_RIGHT_TRANSFER, &ev));
    completer.Reply(std::move(ev));
  }
  void AsyncGetHandleWithTooFewRights(
      AsyncGetHandleWithTooFewRightsCompleter::Sync& completer) override {
    async::PostDelayedTask(
        dispatcher_,
        [completer = completer.ToAsync()]() mutable {
          zx::event ev;
          ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
          ASSERT_EQ(ZX_OK, ev.replace(ZX_RIGHT_TRANSFER, &ev));
          completer.Reply(std::move(ev));
        },
        zx::duration::infinite());
  }
  void SyncGetHandleWithTooManyRights(
      SyncGetHandleWithTooManyRightsCompleter::Sync& completer) override {
    zx::event ev;
    ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
    completer.Reply(std::move(ev));
  }
  void AsyncGetHandleWithTooManyRights(
      AsyncGetHandleWithTooManyRightsCompleter::Sync& completer) override {
    zx::event ev;
    ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
    completer.Reply(std::move(ev));
  }
  void SyncGetHandleWithWrongType(SyncGetHandleWithWrongTypeCompleter::Sync& completer) override {
    zx::event ev;
    ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
    completer.Reply(zx::channel(ev.release()));
  }
  void AsyncGetHandleWithWrongType(AsyncGetHandleWithWrongTypeCompleter::Sync& completer) override {
    zx::event ev;
    ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
    completer.Reply(zx::channel(ev.release()));
  }
  void SendEventWithTransferAndSignal(
      zx::event event, SendEventWithTransferAndSignalCompleter::Sync& completer) override {
    zx_info_handle_basic_t info;
    ASSERT_EQ(ZX_OK, event.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr));
    ASSERT_EQ(ZX_RIGHT_TRANSFER | ZX_RIGHT_SIGNAL, info.rights);
    ASSERT_EQ(ZX_OBJ_TYPE_EVENT, info.type);
  }
  void SendChannel(zx::channel channel, SendChannelCompleter::Sync& completer) override {
    ASSERT_TRUE(false);  // Never should get here.
  }

 private:
  async_dispatcher_t* dispatcher_;
};

class HandleRightsTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigAttachToCurrentThread);
    ASSERT_EQ(loop_->StartThread("test_llcpp_handle_rights_server"), ZX_OK);

    zx::channel server_end;
    ASSERT_EQ(zx::channel::create(0, &client_end_, &server_end), ZX_OK);
    fidl::BindServer(loop_->dispatcher(), std::move(server_end),
                     std::make_unique<HandleRightsServer>());
  }

  test::HandleRights::SyncClient SyncClient() {
    EXPECT_TRUE(client_end_.is_valid());
    return test::HandleRights::SyncClient(std::move(client_end_));
  }

  fidl::Client<test::HandleRights> AsyncClient(test::HandleRights::AsyncEventHandlers handlers) {
    EXPECT_TRUE(client_end_.is_valid());
    return fidl::Client<test::HandleRights>(std::move(client_end_), loop_->dispatcher(),
                                            std::move(handlers));
  }

 private:
  std::unique_ptr<async::Loop> loop_;
  zx::channel client_end_;
};

TEST_F(HandleRightsTest, SyncGetTooFewRights) {
  auto client = SyncClient();
  auto resp = client.SyncGetHandleWithTooFewRights();
  // The channel is closed after a rights error on the sending side.
  ASSERT_EQ(resp.status(), ZX_ERR_PEER_CLOSED);
}

TEST_F(HandleRightsTest, SyncGetTooManyRights) {
  auto client = SyncClient();
  auto resp = client.SyncGetHandleWithTooManyRights();
  ASSERT_TRUE(resp.ok());
  zx_info_handle_basic_t info;
  ASSERT_EQ(ZX_OK, resp->h.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr));
  EXPECT_EQ(ZX_RIGHT_TRANSFER | ZX_RIGHT_SIGNAL, info.rights);
  EXPECT_EQ(ZX_OBJ_TYPE_EVENT, info.type);
}

TEST_F(HandleRightsTest, SyncGetWrongType) {
  auto client = SyncClient();
  auto resp = client.SyncGetHandleWithWrongType();
  // The channel is closed after a object type error on the sending side.
  ASSERT_EQ(resp.status(), ZX_ERR_PEER_CLOSED);
}

TEST_F(HandleRightsTest, SyncSendTooFewRights) {
  auto client = SyncClient();
  zx::event ev;
  ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
  ASSERT_EQ(ZX_OK, ev.replace(ZX_RIGHT_TRANSFER, &ev));
  auto resp = client.SendEventWithTransferAndSignal(std::move(ev));
  // The channel is closed after a rights error on the sending side.
  ASSERT_EQ(resp.status(), ZX_ERR_INVALID_ARGS);
}

TEST_F(HandleRightsTest, SyncSendTooManyRights) {
  auto client = SyncClient();
  zx::event ev;
  ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
  auto resp = client.SendEventWithTransferAndSignal(std::move(ev));
  ASSERT_TRUE(resp.ok());
}

TEST_F(HandleRightsTest, SyncSendWrongType) {
  auto client = SyncClient();
  zx::event ev;
  ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
  // Send the event as a channel (type error).
  auto resp = client.SendChannel(zx::channel(ev.release()));
  // The channel is closed after a type error on the sending side.
  ASSERT_EQ(resp.status(), ZX_ERR_WRONG_TYPE);
}

TEST_F(HandleRightsTest, AsyncSendTooFewRights) {
  auto client = AsyncClient({});
  zx::event ev;
  ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
  ASSERT_EQ(ZX_OK, ev.replace(ZX_RIGHT_TRANSFER, &ev));
  auto resp = client->SendEventWithTransferAndSignal(std::move(ev));
  // The channel is closed after a rights error on the sending side.
  ASSERT_EQ(resp.status(), ZX_ERR_INVALID_ARGS);
}

TEST_F(HandleRightsTest, AsyncSendTooManyRights) {
  auto client = AsyncClient({});
  zx::event ev;
  ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
  auto resp = client->SendEventWithTransferAndSignal(std::move(ev));
  ASSERT_TRUE(resp.ok());
}

TEST_F(HandleRightsTest, AsyncSendWrongType) {
  auto client = AsyncClient({});
  zx::event ev;
  ASSERT_EQ(ZX_OK, zx::event::create(0, &ev));
  // Send the event as a channel (type error).
  auto resp = client->SendChannel(zx::channel(ev.release()));
  // The channel is closed after a type error on the sending side.
  ASSERT_EQ(resp.status(), ZX_ERR_WRONG_TYPE);
}
