// Copyright 2022 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 <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fidl/fuchsia.examples/cpp/fidl.h>
#include <fidl/fuchsia.io/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/namespace.h>
#include <lib/fidl/llcpp/client.h>
#include <lib/service/llcpp/service.h>
#include <lib/sys/component/cpp/constants.h>
#include <lib/sys/component/cpp/outgoing_directory.h>
#include <lib/zx/channel.h>
#include <lib/zx/handle.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/errors.h>

#include <algorithm>
#include <array>
#include <memory>
#include <thread>
#include <utility>

#include <fbl/unique_fd.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <src/lib/storage/vfs/cpp/managed_vfs.h>
#include <src/lib/storage/vfs/cpp/pseudo_dir.h>
#include <src/lib/storage/vfs/cpp/pseudo_file.h>
#include <src/lib/testing/loop_fixture/real_loop_fixture.h>

namespace {

// Expected path of directory hosting FIDL Services & Protocols.
constexpr char kSvcDirectoryPath[] = "svc";

constexpr char kTestString[] = "FizzBuzz";
constexpr char kTestStringReversed[] = "zzuBzziF";

class EchoImpl final : public fidl::WireServer<fuchsia_examples::Echo> {
 public:
  explicit EchoImpl(bool reversed) : reversed_(reversed) {}

  void SendString(SendStringRequestView request, SendStringCompleter::Sync& completer) override {}

  void EchoString(EchoStringRequestView request, EchoStringCompleter::Sync& completer) override {
    std::string value(request->value.get());
    if (reversed_) {
      std::reverse(value.begin(), value.end());
    }
    auto reply = fidl::StringView::FromExternal(value);
    completer.Reply(reply);
  }

 private:
  bool reversed_ = false;
};

class NaturalEchoImpl final : public fidl::Server<fuchsia_examples::Echo> {
 public:
  explicit NaturalEchoImpl(bool reversed) : reversed_(reversed) {}

  void SendString(SendStringRequest& request, SendStringCompleter::Sync& completer) override {}

  void EchoString(EchoStringRequest& request, EchoStringCompleter::Sync& completer) override {
    std::string value(request.value());
    if (reversed_) {
      std::reverse(value.begin(), value.end());
    }
    completer.Reply(value);
  }

 private:
  bool reversed_ = false;
};

class OutgoingDirectoryTest : public gtest::RealLoopFixture {
 public:
  void SetUp() override {
    outgoing_directory_ = std::make_unique<component::OutgoingDirectory>(
        component::OutgoingDirectory::Create(dispatcher()));
    auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
    ZX_ASSERT(outgoing_directory_->Serve(std::move(endpoints->server)).is_ok());
    client_end_ = std::move(endpoints->client);
  }

  component::OutgoingDirectory* GetOutgoingDirectory() { return outgoing_directory_.get(); }

  fidl::ClientEnd<fuchsia_io::Directory> TakeSvcClientEnd(
      fidl::ClientEnd<fuchsia_io::Directory> root, fidl::StringView path = kSvcDirectoryPath) {
    zx::channel server_end, client_end;
    ZX_ASSERT(ZX_OK == zx::channel::create(0, &server_end, &client_end));
    // Check if this has already be initialized.
    if (!svc_client_.is_valid()) {
      svc_client_ = fidl::WireClient<fuchsia_io::Directory>(std::move(root), dispatcher());
    }

    auto status = svc_client_->Open(
        fuchsia_io::wire::OpenFlags::kRightWritable | fuchsia_io::wire::OpenFlags::kRightReadable,
        fuchsia_io::wire::kModeTypeDirectory, path,
        fidl::ServerEnd<fuchsia_io::Node>(std::move(server_end)));
    ZX_ASSERT_MSG(status.ok(), "Failed to open /%s client: %s", path.data(),
                  status.status_string());
    return fidl::ClientEnd<fuchsia_io::Directory>(std::move(client_end));
  }

  fidl::ClientEnd<fuchsia_io::Directory> TakeRootClientEnd() { return std::move(client_end_); }

 protected:
  void InstallServiceHandler(fuchsia_examples::EchoService::Handler& service_handler,
                             EchoImpl* impl, bool reversed) {
    auto handler = [dispatcher = dispatcher(),
                    impl = impl](fidl::ServerEnd<fuchsia_examples::Echo> request) -> void {
      // This is invoked during handler unbound. We're not testing for that
      // here so we just provide a no-op callback.
      auto _on_unbound = [](EchoImpl* impl, fidl::UnbindInfo info,
                            fidl::ServerEnd<fuchsia_examples::Echo> server_end) {};
      fidl::BindServer(dispatcher, std::move(request), impl, std::move(_on_unbound));
    };
    auto result = reversed ? service_handler.add_reversed_echo(std::move(handler))
                           : service_handler.add_regular_echo(std::move(handler));
    ZX_ASSERT(result.is_ok());
  }

  fidl::WireClient<fuchsia_examples::Echo> ConnectToServiceMember(
      fuchsia_examples::EchoService::ServiceClient& service, bool reversed) {
    auto connect_result =
        reversed ? service.connect_reversed_echo() : service.connect_regular_echo();
    ZX_ASSERT(connect_result.is_ok());
    return fidl::WireClient<fuchsia_examples::Echo>(std::move(connect_result.value()),
                                                    dispatcher());
  }

  // Service handler that is pre-populated. This is only used for tests that
  // want to test failure paths.
  component::ServiceHandler CreateNonEmptyServiceHandler() {
    // Setup service handler.
    component::ServiceHandler service_handler;
    fuchsia_examples::EchoService::Handler echo_service_handler(&service_handler);

    // First, install the regular Echo server in this service handler.
    EchoImpl regular_impl(/*reversed=*/false);
    InstallServiceHandler(echo_service_handler, &regular_impl, /*reversed=*/false);
    return service_handler;
  }

 private:
  std::unique_ptr<component::OutgoingDirectory> outgoing_directory_ = nullptr;
  fidl::ClientEnd<fuchsia_io::Directory> client_end_;
  fidl::WireClient<fuchsia_io::Directory> svc_client_;
};

TEST_F(OutgoingDirectoryTest, AddProtocolWireServer) {
  // Setup fuchsia.examples.Echo server.
  EchoImpl impl(/*reversed=*/false);
  ASSERT_EQ(GetOutgoingDirectory()->AddProtocol<fuchsia_examples::Echo>(&impl).status_value(),
            ZX_OK);

  // Setup fuchsia.examples.Echo client.
  auto client_end =
      service::ConnectAt<fuchsia_examples::Echo>(TakeSvcClientEnd(TakeRootClientEnd()));
  ASSERT_EQ(client_end.status_value(), ZX_OK);
  fidl::WireClient<fuchsia_examples::Echo> client(std::move(*client_end), dispatcher());

  std::string reply_received;
  client->EchoString(kTestString)
      .ThenExactlyOnce([&reply_received, quit_loop = QuitLoopClosure()](
                           fidl::WireUnownedResult<fuchsia_examples::Echo::EchoString>& result) {
        ASSERT_TRUE(result.ok()) << "EchoString failed: " << result.error();
        auto* response = result.Unwrap();
        reply_received = std::string(response->response.data(), response->response.size());
        quit_loop();
      });
  RunLoop();

  EXPECT_EQ(reply_received, kTestString);
}

TEST_F(OutgoingDirectoryTest, AddProtocolNaturalServer) {
  // Setup fuchsia.examples.Echo server.
  NaturalEchoImpl impl(/*reversed=*/false);
  ASSERT_EQ(GetOutgoingDirectory()->AddProtocol<fuchsia_examples::Echo>(&impl).status_value(),
            ZX_OK);

  // Setup fuchsia.examples.Echo client.
  auto client_end =
      service::ConnectAt<fuchsia_examples::Echo>(TakeSvcClientEnd(TakeRootClientEnd()));
  ASSERT_EQ(client_end.status_value(), ZX_OK);
  fidl::Client<fuchsia_examples::Echo> client(std::move(*client_end), dispatcher());

  std::string reply_received;
  client->EchoString({kTestString})
      .ThenExactlyOnce([&reply_received, quit_loop = QuitLoopClosure()](
                           fidl::Result<fuchsia_examples::Echo::EchoString>& result) {
        ASSERT_TRUE(result.is_ok()) << "EchoString failed: " << result.error_value();
        reply_received = result->response();
        quit_loop();
      });
  RunLoop();

  EXPECT_EQ(reply_received, kTestString);
}

// Test that outgoing directory is able to serve multiple service members. In
// this case, the directory will host the `fuchsia.examples.EchoService` which
// contains two `fuchsia.examples.Echo` member. One regular, and one reversed.
TEST_F(OutgoingDirectoryTest, AddServiceServesAllMembers) {
  // Setup service handler.
  component::ServiceHandler service_handler;
  fuchsia_examples::EchoService::Handler echo_service_handler(&service_handler);

  // First, install the regular Echo server in this service handler.
  EchoImpl regular_impl(/*reversed=*/false);
  InstallServiceHandler(echo_service_handler, &regular_impl, /*reversed=*/false);

  // Then, install the reverse Echo server. This instance will reverse the string
  // received in calls to EchoString.
  EchoImpl reversed_impl(/*reversed=*/true);
  InstallServiceHandler(echo_service_handler, &reversed_impl, /*reversed=*/true);

  ZX_ASSERT(GetOutgoingDirectory()
                ->AddService<fuchsia_examples::EchoService>(std::move(service_handler))
                .is_ok());

  // Setup test client.
  auto open_result =
      service::OpenServiceAt<fuchsia_examples::EchoService>(TakeSvcClientEnd(TakeRootClientEnd()));
  ZX_ASSERT(open_result.is_ok());

  fuchsia_examples::EchoService::ServiceClient service = std::move(open_result.value());

  // Assert that service is connected and that proper impl returns expected reply.
  for (bool reversed : {true, false}) {
    bool message_echoed = false;
    auto client = ConnectToServiceMember(service, reversed);
    auto expected_reply = reversed ? kTestStringReversed : kTestString;
    client->EchoString(kTestString)
        .ThenExactlyOnce(
            [quit_loop = QuitLoopClosure(), &message_echoed, expected_reply = expected_reply](
                fidl::WireUnownedResult<fuchsia_examples::Echo::EchoString>& reply) {
              EXPECT_TRUE(reply.ok()) << "Reply failed with: " << reply.error().status_string();
              EXPECT_EQ(reply.value().response.get(), cpp17::string_view(expected_reply));
              message_echoed = true;
              quit_loop();
            });

    RunLoop();

    EXPECT_TRUE(message_echoed);
  }

  // Next, assert that after removing the service, the client end yields ZX_ERR_PEER_CLOSED.
  ZX_ASSERT(GetOutgoingDirectory()->RemoveService<fuchsia_examples::EchoService>().is_ok());
  for (bool reversed : {true, false}) {
    auto connect_result =
        reversed ? service.connect_reversed_echo() : service.connect_regular_echo();
    ZX_ASSERT(connect_result.is_error());
    EXPECT_EQ(connect_result.status_value(), ZX_ERR_PEER_CLOSED);
  }
}

// Test that serving a FIDL Protocol works as expected.
TEST_F(OutgoingDirectoryTest, AddProtocolCanServeMultipleProtocols) {
  constexpr static std::array<std::pair<bool, const char*>, 2> kIsReversedAndPaths = {
      {{false, "fuchsia.examples.Echo"}, {true, "fuchsia.examples.Ohce"}}};

  // Setup fuchsia.examples.Echo servers
  EchoImpl regular_impl(/*reversed=*/false);
  EchoImpl reversed_impl(/*reversed=*/true);
  for (auto [reversed, path] : kIsReversedAndPaths) {
    auto* impl = reversed ? &reversed_impl : &regular_impl;
    ASSERT_EQ(
        GetOutgoingDirectory()->AddProtocol<fuchsia_examples::Echo>(impl, path).status_value(),
        ZX_OK);
  }

  // Setup fuchsia.examples.Echo client
  for (auto [reversed, path] : kIsReversedAndPaths) {
    auto client_end =
        service::ConnectAt<fuchsia_examples::Echo>(TakeSvcClientEnd(TakeRootClientEnd()), path);
    ASSERT_EQ(client_end.status_value(), ZX_OK);
    fidl::WireClient<fuchsia_examples::Echo> client(std::move(*client_end), dispatcher());

    std::string reply_received;
    client->EchoString(kTestString)
        .ThenExactlyOnce([&reply_received, quit_loop = QuitLoopClosure()](
                             fidl::WireUnownedResult<fuchsia_examples::Echo::EchoString>& result) {
          ASSERT_TRUE(result.ok()) << "EchoString failed: " << result.error();
          auto* response = result.Unwrap();
          reply_received = std::string(response->response.data(), response->response.size());
          quit_loop();
        });
    RunLoop();

    auto expected_reply = reversed ? kTestStringReversed : kTestString;
    EXPECT_EQ(reply_received, expected_reply);
  }
}

// Test that after removing protocol, all clients are unable to make a call on
// the channel.
TEST_F(OutgoingDirectoryTest, RemoveProtocolClosesAllConnections) {
  // For this test case, 3 clients will connect to one Echo protocol.
  static constexpr size_t kNumClients = 3;

  class EventHandler : public fidl::AsyncEventHandler<fuchsia_examples::Echo> {
   public:
    EventHandler() = default;

    void on_fidl_error(fidl::UnbindInfo error) override { errors_.emplace_back(error); }

    std::vector<fidl::UnbindInfo> GetErrors() { return errors_; }

   private:
    std::vector<fidl::UnbindInfo> errors_;
  };

  EventHandler event_handler;
  EchoImpl regular_impl(/*reversed=*/false);
  ASSERT_EQ(
      GetOutgoingDirectory()->AddProtocol<fuchsia_examples::Echo>(&regular_impl).status_value(),
      ZX_OK);

  fidl::ClientEnd<fuchsia_io::Directory> svc_directory = TakeSvcClientEnd(TakeRootClientEnd());
  std::vector<fidl::Client<fuchsia_examples::Echo>> clients = {};
  for (size_t i = 0; i < kNumClients; ++i) {
    auto client_end = service::ConnectAt<fuchsia_examples::Echo>(svc_directory.borrow());

    ASSERT_EQ(client_end.status_value(), ZX_OK);

    fidl::Client<fuchsia_examples::Echo> client(std::move(*client_end), dispatcher(),
                                                &event_handler);
    client->EchoString(std::string(kTestString))
        .ThenExactlyOnce([quit_loop = QuitLoopClosure()](
                             fidl::Result<fuchsia_examples::Echo::EchoString>& result) {
          ASSERT_TRUE(result.is_ok());
          ASSERT_EQ(result->response(), kTestString);
          quit_loop();
        });
    RunLoop();

    clients.emplace_back(std::move(client));
  }

  ASSERT_EQ(GetOutgoingDirectory()->RemoveProtocol<fuchsia_examples::Echo>().status_value(), ZX_OK);
  RunLoopUntilIdle();

  ASSERT_EQ(event_handler.GetErrors().size(), kNumClients);
  for (auto& error : event_handler.GetErrors()) {
    EXPECT_TRUE(error.is_peer_closed())
        << "Expected peer_closed. Got : " << error.FormatDescription();
  }
}

// Test that serving a FIDL Protocol from a non-svc directory works as expected.
TEST_F(OutgoingDirectoryTest, AddProtocolAtServesProtocol) {
  constexpr static char kDirectory[] = "test";

  // Setup fuchsia.examples.Echo servers
  EchoImpl regular_impl(/*reversed=*/false);
  ASSERT_EQ(GetOutgoingDirectory()
                ->AddProtocolAt<fuchsia_examples::Echo>(kDirectory, &regular_impl)
                .status_value(),
            ZX_OK);

  auto client_end = service::ConnectAt<fuchsia_examples::Echo>(
      TakeSvcClientEnd(TakeRootClientEnd(), /*path=*/kDirectory));
  ASSERT_EQ(client_end.status_value(), ZX_OK);
  fidl::WireClient<fuchsia_examples::Echo> client(std::move(*client_end), dispatcher());

  std::string reply_received;
  client->EchoString(kTestString)
      .ThenExactlyOnce([&reply_received, quit_loop = QuitLoopClosure()](
                           fidl::WireUnownedResult<fuchsia_examples::Echo::EchoString>& result) {
        ASSERT_TRUE(result.ok()) << "EchoString failed: " << result.error().FormatDescription();
        auto* response = result.Unwrap();
        reply_received = std::string(response->response.data(), response->response.size());
        quit_loop();
      });
  RunLoop();

  EXPECT_EQ(reply_received, kTestString);
}

TEST_F(OutgoingDirectoryTest, AddDirectoryCanServeADirectory) {
  static constexpr char kTestDirectory[] = "diagnostics";
  static constexpr char kTestFile[] = "sample.txt";
  static constexpr char kTestContent[] = "Hello World!";

  fs::ManagedVfs vfs(dispatcher());
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  auto text_file = fbl::MakeRefCounted<fs::BufferedPseudoFile>(
      /*read_handler=*/[](fbl::String* output) -> zx_status_t {
        *output = kTestContent;
        return ZX_OK;
      });
  auto diagnostics = fbl::MakeRefCounted<fs::PseudoDir>();
  diagnostics->AddEntry(kTestFile, text_file);
  vfs.ServeDirectory(diagnostics, std::move(endpoints->server));
  ASSERT_EQ(GetOutgoingDirectory()
                ->AddDirectory(std::move(endpoints->client), kTestDirectory)
                .status_value(),
            ZX_OK);

  std::thread([client_end = TakeRootClientEnd().TakeChannel().release(),
               quit_loop = QuitLoopClosure()]() {
    fbl::unique_fd root_fd;
    ASSERT_EQ(fdio_fd_create(client_end, root_fd.reset_and_get_address()), ZX_OK);
    ZX_ASSERT_MSG(root_fd.is_valid(), "Failed to open root ns as a file descriptor: %s",
                  strerror(errno));

    fbl::unique_fd dir_fd(openat(root_fd.get(), kTestDirectory, O_DIRECTORY));
    ZX_ASSERT_MSG(dir_fd.is_valid(), "Failed to open directory \"%s\": %s", kTestDirectory,
                  strerror(errno));

    fbl::unique_fd filefd(openat(dir_fd.get(), kTestFile, O_RDONLY));
    ZX_ASSERT_MSG(filefd.is_valid(), "Failed to open file \"%s\": %s", kTestFile, strerror(errno));
    static constexpr size_t kMaxBufferSize = 1024;
    static char kReadBuffer[kMaxBufferSize];
    size_t bytes_read = read(filefd.get(), reinterpret_cast<void*>(kReadBuffer), kMaxBufferSize);
    ZX_ASSERT_MSG(bytes_read > 0, "Read 0 bytes from file at \"%s\": %s", kTestFile,
                  strerror(errno));

    std::string actual_content(kReadBuffer, bytes_read);
    EXPECT_EQ(actual_content, kTestContent);
    quit_loop();
  }).detach();

  RunLoop();

  vfs.Shutdown([quit_loop = QuitLoopClosure()](zx_status_t status) {
    ASSERT_EQ(status, ZX_OK);
    quit_loop();
  });
  RunLoop();

  EXPECT_EQ(GetOutgoingDirectory()->RemoveDirectory(kTestDirectory).status_value(), ZX_OK);
}

// Test that we can connect to the outgoing directory via multiple connections.
TEST_F(OutgoingDirectoryTest, ServeCanYieldMultipleConnections) {
  // Setup fuchsia.examples.Echo server
  EchoImpl regular_impl(/*reversed=*/false);
  ASSERT_EQ(
      GetOutgoingDirectory()->AddProtocol<fuchsia_examples::Echo>(&regular_impl).status_value(),
      ZX_OK);

  // Setup fuchsia.examples.Echo client
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  // First |Serve| is invoked as part of test setup, so we'll assert that a
  // subsequent invocation is allowed.
  ASSERT_EQ(GetOutgoingDirectory()->Serve(std::move(endpoints->server)).status_value(), ZX_OK);

  std::vector<fidl::ClientEnd<fuchsia_io::Directory>> root_client_ends;
  // Take client end for channel used during invocation of |Serve| during setup.
  root_client_ends.emplace_back(TakeRootClientEnd());
  // Take client end for channel used during invocation of |Serve| in this function.
  root_client_ends.emplace_back(std::move(endpoints->client));

  while (!root_client_ends.empty()) {
    auto root = std::move(root_client_ends.back());
    root_client_ends.pop_back();

    auto client_end =
        service::ConnectAt<fuchsia_examples::Echo>(TakeSvcClientEnd(/*root=*/std::move(root)));
    ASSERT_EQ(client_end.status_value(), ZX_OK);
    fidl::WireClient<fuchsia_examples::Echo> client(std::move(*client_end), dispatcher());

    std::string reply_received;
    client->EchoString(kTestString)
        .ThenExactlyOnce([&reply_received, quit_loop = QuitLoopClosure()](
                             fidl::WireUnownedResult<fuchsia_examples::Echo::EchoString>& result) {
          ASSERT_TRUE(result.ok()) << "EchoString failed: " << result.error();
          auto* response = result.Unwrap();
          reply_received = std::string(response->response.data(), response->response.size());
          quit_loop();
        });
    RunLoop();

    EXPECT_EQ(reply_received, kTestString);
  }
}

TEST_F(OutgoingDirectoryTest, CreateFailsIfDispatcherIsNullptr) {
  ASSERT_DEATH(
      { auto outgoing_directory = component::OutgoingDirectory::Create(/*dispatcher=*/nullptr); },
      "");
}

TEST_F(OutgoingDirectoryTest, ServeFailsIfHandleInvalid) {
  auto outgoing_directory = component::OutgoingDirectory::Create(dispatcher());
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  // Close server end in order to  invalidate channel.
  endpoints->server.reset();
  EXPECT_EQ(outgoing_directory.Serve(std::move(endpoints->server)).status_value(),
            ZX_ERR_BAD_HANDLE);
}

TEST_F(OutgoingDirectoryTest, AddServiceFailsIfInstanceNameIsEmpty) {
  EXPECT_EQ(GetOutgoingDirectory()
                ->AddService<fuchsia_examples::EchoService>(CreateNonEmptyServiceHandler(),
                                                            /*instance=*/"")
                .status_value(),
            ZX_ERR_INVALID_ARGS);
}

TEST_F(OutgoingDirectoryTest, AddServiceFailsIfEntryExists) {
  ASSERT_EQ(GetOutgoingDirectory()
                ->AddService<fuchsia_examples::EchoService>(CreateNonEmptyServiceHandler())
                .status_value(),
            ZX_OK);

  EXPECT_EQ(GetOutgoingDirectory()
                ->AddService<fuchsia_examples::EchoService>(CreateNonEmptyServiceHandler())
                .status_value(),
            ZX_ERR_ALREADY_EXISTS);
}

TEST_F(OutgoingDirectoryTest, AddServiceFailsIfServiceHandlerEmpty) {
  EXPECT_EQ(GetOutgoingDirectory()
                ->AddService<fuchsia_examples::EchoService>(component::ServiceHandler())
                .status_value(),
            ZX_ERR_INVALID_ARGS);
}

TEST_F(OutgoingDirectoryTest, AddServiceFailsIfServiceNameIsEmpty) {
  EXPECT_EQ(GetOutgoingDirectory()
                ->AddService(CreateNonEmptyServiceHandler(), /*service=*/"",
                             /*instance=*/component::kDefaultInstance)
                .status_value(),
            ZX_ERR_INVALID_ARGS);
}

TEST_F(OutgoingDirectoryTest, AddProtocolFailsIfImplIsNullptr) {
  EXPECT_EQ(GetOutgoingDirectory()
                ->AddProtocol<fuchsia_examples::Echo>(
                    /*impl*/ static_cast<fidl::WireServer<fuchsia_examples::Echo>*>(nullptr))
                .status_value(),
            ZX_ERR_INVALID_ARGS);
  EXPECT_EQ(GetOutgoingDirectory()
                ->AddProtocol<fuchsia_examples::Echo>(
                    /*impl*/ static_cast<fidl::Server<fuchsia_examples::Echo>*>(nullptr))
                .status_value(),
            ZX_ERR_INVALID_ARGS);
}

TEST_F(OutgoingDirectoryTest, AddProtocolFailsIfNameIsEmpty) {
  EchoImpl regular_impl(/*reversed=*/false);
  EXPECT_EQ(GetOutgoingDirectory()
                ->AddProtocol<fuchsia_examples::Echo>(&regular_impl, /*name=*/"")
                .status_value(),
            ZX_ERR_INVALID_ARGS);
}

TEST_F(OutgoingDirectoryTest, AddProtocolFailsIfEntryExists) {
  EchoImpl regular_impl(/*reversed=*/false);
  ASSERT_EQ(
      GetOutgoingDirectory()->AddProtocol<fuchsia_examples::Echo>(&regular_impl).status_value(),
      ZX_OK);

  EXPECT_EQ(
      GetOutgoingDirectory()->AddProtocol<fuchsia_examples::Echo>(&regular_impl).status_value(),
      ZX_ERR_ALREADY_EXISTS);
}

TEST_F(OutgoingDirectoryTest, AddProtocolAtFailsIfDirectoryIsEmpty) {
  EchoImpl regular_impl(/*reversed=*/false);
  EXPECT_EQ(GetOutgoingDirectory()
                ->AddProtocolAt<fuchsia_examples::Echo>(/*directory=*/"", &regular_impl)
                .status_value(),
            ZX_ERR_INVALID_ARGS);
}

TEST_F(OutgoingDirectoryTest, AddDirectoryFailsIfRemoteDirInvalid) {
  fidl::ClientEnd<fuchsia_io::Directory> dangling_client_end;
  ASSERT_FALSE(dangling_client_end.is_valid());

  EXPECT_EQ(GetOutgoingDirectory()
                ->AddDirectory(std::move(dangling_client_end), "AValidName")
                .status_value(),
            ZX_ERR_BAD_HANDLE);
}

TEST_F(OutgoingDirectoryTest, AddDirectoryFailsIfDirectoryNameIsEmpty) {
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();

  EXPECT_EQ(GetOutgoingDirectory()
                ->AddDirectory(std::move(endpoints->client), /*directory_name=*/"")
                .status_value(),
            ZX_ERR_INVALID_ARGS);
}

TEST_F(OutgoingDirectoryTest, AddDirectoryFailsIfEntryExists) {
  constexpr char kDirectoryName[] = "test";

  for (auto expected_status : {ZX_OK, ZX_ERR_ALREADY_EXISTS}) {
    auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
    EXPECT_EQ(GetOutgoingDirectory()
                  ->AddDirectory(std::move(endpoints->client), kDirectoryName)
                  .status_value(),
              expected_status);
  }
}

TEST_F(OutgoingDirectoryTest, AddDirectoryFailsIfNameUsedForAddProtocolAt) {
  constexpr char kDirectoryName[] = "diagnostics";

  EchoImpl regular_impl(/*reversed=*/false);
  ASSERT_EQ(GetOutgoingDirectory()
                ->AddProtocolAt<fuchsia_examples::Echo>(kDirectoryName, &regular_impl)
                .status_value(),
            ZX_OK);

  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  EXPECT_EQ(GetOutgoingDirectory()
                ->AddDirectory(std::move(endpoints->client), kDirectoryName)
                .status_value(),
            ZX_ERR_ALREADY_EXISTS);
}

TEST_F(OutgoingDirectoryTest, RemoveServiceFailsIfEntryDoesNotExist) {
  EXPECT_EQ(GetOutgoingDirectory()->RemoveService<fuchsia_examples::EchoService>().status_value(),
            ZX_ERR_NOT_FOUND);
}

TEST_F(OutgoingDirectoryTest, RemoveProtocolFailsIfEntryDoesNotExist) {
  EXPECT_EQ(GetOutgoingDirectory()->RemoveProtocol<fuchsia_examples::Echo>().status_value(),
            ZX_ERR_NOT_FOUND);
}

TEST_F(OutgoingDirectoryTest, RemoveDirectoryFailsIfEntryDoesNotExist) {
  EXPECT_EQ(GetOutgoingDirectory()->RemoveDirectory(/*directory_name=*/"test").status_value(),
            ZX_ERR_NOT_FOUND);
}

class OutgoingDirectoryPathParameterizedFixture
    : public testing::TestWithParam<std::pair<std::string, std::string>> {};

TEST_P(OutgoingDirectoryPathParameterizedFixture, BadServicePaths) {
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  auto outgoing_directory = component::OutgoingDirectory::Create(loop.dispatcher());
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
  ZX_ASSERT(outgoing_directory.Serve(std::move(endpoints->server)).is_ok());
  component::ServiceHandler service_handler;
  fuchsia_examples::EchoService::Handler echo_service_handler(&service_handler);
  EchoImpl regular_impl(/*reversed=*/false);
  auto noop_handler = [](fidl::ServerEnd<fuchsia_examples::Echo> _request) -> void {};
  ZX_ASSERT(echo_service_handler.add_regular_echo(std::move(noop_handler)).is_ok());

  auto service_and_instance_names = GetParam();
  EXPECT_EQ(outgoing_directory
                .AddService(component::ServiceHandler(), service_and_instance_names.first,
                            service_and_instance_names.second)
                .status_value(),
            ZX_ERR_INVALID_ARGS);
}

INSTANTIATE_TEST_SUITE_P(OutgoingDirectoryTestPathTest, OutgoingDirectoryPathParameterizedFixture,
                         testing::Values(std::make_pair("", component::kDefaultInstance),
                                         std::make_pair(".", component::kDefaultInstance),
                                         std::make_pair("fuchsia.examples.EchoService", ""),
                                         std::make_pair("fuchsia.examples.EchoService", "")));

}  // namespace
