blob: 38786d4ff7766ef72a04b85d887ed93407978b8b [file] [log] [blame]
// 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 <fuchsia/io/c/fidl.h>
#include <fuchsia/io/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/cpp/message_buffer.h>
#include <lib/gtest/real_loop_fixture.h>
#include <lib/sys/cpp/outgoing_directory.h>
#include <lib/zx/channel.h>
#include "echo_server.h"
#include "gtest/gtest.h"
namespace {
using OutgoingDirectorySetupTest = gtest::RealLoopFixture;
class OutgoingDirectoryTest : public gtest::RealLoopFixture {
protected:
void SetUp() override {
gtest::RealLoopFixture::SetUp();
zx::channel svc_server;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &svc_client_, &svc_server));
ASSERT_EQ(ZX_OK, outgoing_.Serve(std::move(svc_server), dispatcher()));
}
void TestCanAccessEchoService(const char* service_path,
bool succeeds = true) {
fidl::examples::echo::EchoPtr echo;
fdio_service_connect_at(
svc_client_.get(), service_path,
echo.NewRequest(dispatcher()).TakeChannel().release());
std::string result = "no callback";
echo->EchoString("hello",
[&result](fidl::StringPtr value) { result = *value; });
RunLoopUntilIdle();
EXPECT_EQ(succeeds ? "hello" : "no callback", result);
}
void AddEchoService(vfs::PseudoDir* dir) {
ASSERT_EQ(ZX_OK, dir->AddEntry(fidl::examples::echo::Echo::Name_,
std::make_unique<vfs::Service>(
echo_impl_.GetHandler(dispatcher()))));
}
EchoImpl echo_impl_;
zx::channel svc_client_;
sys::OutgoingDirectory outgoing_;
};
TEST_F(OutgoingDirectoryTest, Control) {
ASSERT_EQ(ZX_OK,
outgoing_.AddPublicService(echo_impl_.GetHandler(dispatcher())));
TestCanAccessEchoService("public/fidl.examples.echo.Echo");
// Ensure GetOrCreateDirectory refers to the same "public" directory.
outgoing_.GetOrCreateDirectory("public")->RemoveEntry(
"fidl.examples.echo.Echo");
TestCanAccessEchoService("public/fidl.examples.echo.Echo", false);
}
TEST_F(OutgoingDirectoryTest, AddAndRemove) {
ASSERT_EQ(ZX_ERR_NOT_FOUND,
outgoing_.RemovePublicService<fidl::examples::echo::Echo>());
ASSERT_EQ(ZX_OK,
outgoing_.AddPublicService(echo_impl_.GetHandler(dispatcher())));
ASSERT_EQ(ZX_ERR_ALREADY_EXISTS,
outgoing_.AddPublicService(echo_impl_.GetHandler(dispatcher())));
TestCanAccessEchoService("public/fidl.examples.echo.Echo");
ASSERT_EQ(ZX_OK, outgoing_.RemovePublicService<fidl::examples::echo::Echo>());
ASSERT_EQ(ZX_ERR_NOT_FOUND,
outgoing_.RemovePublicService<fidl::examples::echo::Echo>());
TestCanAccessEchoService("public/fidl.examples.echo.Echo", false);
}
TEST_F(OutgoingDirectoryTest, DebugDir) {
AddEchoService(outgoing_.debug_dir());
TestCanAccessEchoService("debug/fidl.examples.echo.Echo");
outgoing_.GetOrCreateDirectory("debug")->RemoveEntry(
"fidl.examples.echo.Echo");
TestCanAccessEchoService("debug/fidl.examples.echo.Echo", false);
}
TEST_F(OutgoingDirectoryTest, GetOrCreateDirectory) {
outgoing_.GetOrCreateDirectory("objects")->AddEntry(
"test_svc_a",
std::make_unique<vfs::Service>(echo_impl_.GetHandler(dispatcher())));
outgoing_.GetOrCreateDirectory("objects")->AddEntry(
"test_svc_b",
std::make_unique<vfs::Service>(echo_impl_.GetHandler(dispatcher())));
TestCanAccessEchoService("objects/test_svc_a");
TestCanAccessEchoService("objects/test_svc_b");
}
TEST_F(OutgoingDirectorySetupTest, Invalid) {
sys::OutgoingDirectory outgoing;
// TODO: This should return ZX_ERR_BAD_HANDLE.
ASSERT_EQ(ZX_OK, outgoing.Serve(zx::channel(), dispatcher()));
}
TEST_F(OutgoingDirectorySetupTest, AccessDenied) {
zx::channel svc_client, svc_server;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &svc_client, &svc_server));
svc_server.replace(ZX_RIGHT_NONE, &svc_server);
sys::OutgoingDirectory outgoing;
ASSERT_EQ(ZX_ERR_ACCESS_DENIED,
outgoing.Serve(std::move(svc_server), dispatcher()));
}
} // namespace