// 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/wait.h>
#include <lib/fidl-async/cpp/bind.h>
#include <zircon/fidl.h>
#include <zircon/status.h>

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

namespace test = ::llcpp::llcpptest::transitional::test;

namespace {

class Server : public test::TransitionMethods::Interface {
 public:
  void ImplementedMethod(ImplementedMethodCompleter::Sync& txn) override {
    // Reply call to maintain an open connection.
    txn.Reply(fidl::StringView("test reply"));
  }

  void Bind(fidl::ServerEnd<test::TransitionMethods> server, async::Loop* loop) {
    zx_status_t bind_status =
        fidl::BindSingleInFlightOnly(loop->dispatcher(), std::move(server), this);
    EXPECT_EQ(bind_status, ZX_OK);
  }
};

class TransitionalTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigAttachToCurrentThread);
    ASSERT_EQ(loop_->StartThread("test_llcpp_transitional_server"), ZX_OK);
    auto endpoints = fidl::CreateEndpoints<test::TransitionMethods>();
    ASSERT_EQ(endpoints.status_value(), ZX_OK);
    client_end_ = std::move(endpoints->client);
    server_ = std::make_unique<Server>();
    server_->Bind(std::move(endpoints->server), loop_.get());
  }

  virtual void TearDown() {
    loop_->Quit();
    loop_->JoinThreads();
  }

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

 private:
  std::unique_ptr<async::Loop> loop_;
  std::unique_ptr<Server> server_;
  fidl::ClientEnd<test::TransitionMethods> client_end_;
};

// The implemented call should succeed.
TEST_F(TransitionalTest, CallImplementedMethod) {
  auto client = TakeClient();
  auto result = client.ImplementedMethod();
  EXPECT_TRUE(result.ok());
  EXPECT_EQ(result.error(), nullptr) << result.error();
  ASSERT_EQ(result.status(), ZX_OK) << zx_status_get_string(result.status());
}

// The unimplemented transitional call should error with not supported in an
// epitaph. However, epitaphs are currently not supported (fxbug.dev/35445) so the
// server closes the connection on an unsupported call. This results in a peer
// connection closed error instead.
TEST_F(TransitionalTest, CallUnimplementedMethod) {
  auto client = TakeClient();
  auto result = client.UnimplementedMethod();
  EXPECT_FALSE(result.ok());
  EXPECT_EQ(std::string("failed writing to the underlying transport"), result.error())
      << result.error();
  ASSERT_EQ(result.status(), ZX_ERR_PEER_CLOSED) << zx_status_get_string(result.status());
}

}  // namespace
