| // 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 |