| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/fuchsia/fidl_event_handler.h" |
| |
| #include <fidl/base.testfidl/cpp/fidl.h> |
| #include <fidl/fuchsia.logger/cpp/fidl.h> |
| #include <lib/sys/cpp/component_context.h> |
| |
| #include "base/fuchsia/fuchsia_component_connect.h" |
| #include "base/fuchsia/process_context.h" |
| #include "base/fuchsia/scoped_service_binding.h" |
| #include "base/fuchsia/test_component_context_for_process.h" |
| #include "base/fuchsia/test_interface_natural_impl.h" |
| #include "base/fuchsia/test_log_listener_safe.h" |
| #include "base/task/thread_pool.h" |
| #include "base/test/bind.h" |
| #include "base/test/scoped_logging_settings.h" |
| #include "base/test/task_environment.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| constexpr char kBaseUnittestsExec[] = "base_unittests__exec"; |
| |
| } // namespace |
| |
| namespace base { |
| |
| class FidlEventHandlerTest : public testing::Test { |
| public: |
| FidlEventHandlerTest() { |
| test_context_.AddService( |
| fidl::DiscoverableProtocolName<fuchsia_logger::Log>); |
| ListenFilteredByCurrentProcessId(listener_); |
| // Initialize logging in the `scoped_logging_settings_`. |
| CHECK(logging::InitLogging({.logging_dest = logging::LOG_DEFAULT})); |
| } |
| FidlEventHandlerTest(const FidlEventHandlerTest&) = delete; |
| FidlEventHandlerTest& operator=(const FidlEventHandlerTest&) = delete; |
| ~FidlEventHandlerTest() override = default; |
| |
| protected: |
| test::SingleThreadTaskEnvironment task_environment_{ |
| test::SingleThreadTaskEnvironment::MainThreadType::IO}; |
| SimpleTestLogListener listener_; |
| |
| // Ensure that logging is directed to the system debug log. |
| logging::ScopedLoggingSettings scoped_logging_settings_; |
| TestComponentContextForProcess test_context_; |
| TestInterfaceNaturalImpl test_service_; |
| }; |
| |
| TEST_F(FidlEventHandlerTest, FidlErrorEventLogger) { |
| FidlErrorEventLogger<base_testfidl::TestInterface> event_handler; |
| |
| event_handler.on_fidl_error(fidl::UnbindInfo::PeerClosed(ZX_ERR_PEER_CLOSED)); |
| |
| constexpr char kLogMessage[] = |
| "base.testfidl.TestInterface was disconnected with ZX_ERR_PEER_CLOSED"; |
| absl::optional<fuchsia_logger::LogMessage> logged_message = |
| listener_.RunUntilMessageReceived(kLogMessage); |
| |
| ASSERT_TRUE(logged_message.has_value()); |
| EXPECT_EQ(logged_message->severity(), |
| static_cast<int32_t>(fuchsia_logger::LogLevelFilter::kError)); |
| ASSERT_EQ(logged_message->tags().size(), 1u); |
| EXPECT_EQ(logged_message->tags()[0], kBaseUnittestsExec); |
| } |
| |
| TEST_F(FidlEventHandlerTest, FidlErrorEventLogger_CustomProtocolName) { |
| FidlErrorEventLogger<base_testfidl::TestInterface> event_handler( |
| "test_protocol_name"); |
| |
| event_handler.on_fidl_error(fidl::UnbindInfo::PeerClosed(ZX_ERR_PEER_CLOSED)); |
| |
| constexpr char kLogMessage[] = |
| "test_protocol_name was disconnected with ZX_ERR_PEER_CLOSED"; |
| absl::optional<fuchsia_logger::LogMessage> logged_message = |
| listener_.RunUntilMessageReceived(kLogMessage); |
| |
| ASSERT_TRUE(logged_message.has_value()); |
| EXPECT_EQ(logged_message->severity(), |
| static_cast<int32_t>(fuchsia_logger::LogLevelFilter::kError)); |
| ASSERT_EQ(logged_message->tags().size(), 1u); |
| EXPECT_EQ(logged_message->tags()[0], kBaseUnittestsExec); |
| } |
| |
| TEST_F(FidlEventHandlerTest, FidlErrorEventLogger_LogsOnServiceClosure) { |
| FidlErrorEventLogger<base_testfidl::TestInterface> event_handler; |
| auto client_end = fuchsia_component::ConnectAt<base_testfidl::TestInterface>( |
| test_context_.published_services_natural()); |
| EXPECT_TRUE(client_end.is_ok()); |
| fidl::Client client(std::move(*client_end), async_get_default_dispatcher(), |
| &event_handler); |
| |
| { |
| ScopedNaturalServiceBinding<base_testfidl::TestInterface> binding( |
| ComponentContextForProcess()->outgoing().get(), &test_service_); |
| |
| ASSERT_EQ(ZX_OK, VerifyTestInterface(client)); |
| }; |
| |
| constexpr char kLogMessage[] = |
| "base.testfidl.TestInterface was disconnected with ZX_ERR_PEER_CLOSED"; |
| absl::optional<fuchsia_logger::LogMessage> logged_message = |
| listener_.RunUntilMessageReceived(kLogMessage); |
| |
| ASSERT_TRUE(logged_message.has_value()); |
| EXPECT_EQ(logged_message->severity(), |
| static_cast<int32_t>(fuchsia_logger::LogLevelFilter::kError)); |
| ASSERT_EQ(logged_message->tags().size(), 1u); |
| EXPECT_EQ(logged_message->tags()[0], kBaseUnittestsExec); |
| } |
| |
| TEST(FidlEventHandlerDeathTest, FidlErrorEventProcessExiter) { |
| FidlErrorEventProcessExiter<base_testfidl::TestInterface> event_handler; |
| |
| EXPECT_DEATH( |
| event_handler.on_fidl_error( |
| fidl::UnbindInfo::PeerClosed(ZX_ERR_PEER_CLOSED)), |
| testing::HasSubstr("base.testfidl.TestInterface disconnected " |
| "unexpectedly, exiting: ZX_ERR_PEER_CLOSED (-24)")); |
| } |
| |
| TEST(FidlEventHandlerDeathTest, |
| FidlErrorEventProcessExiter_CustomProtocolName) { |
| FidlErrorEventProcessExiter<base_testfidl::TestInterface> event_handler( |
| "test_protocol_name"); |
| |
| EXPECT_DEATH( |
| event_handler.on_fidl_error( |
| fidl::UnbindInfo::PeerClosed(ZX_ERR_PEER_CLOSED)), |
| testing::HasSubstr("test_protocol_name disconnected unexpectedly, " |
| "exiting: ZX_ERR_PEER_CLOSED (-24)")); |
| } |
| |
| TEST(FidlEventHandlerDeathTest, |
| FidlErrorEventProcessExiter_LogsOnServiceClosure) { |
| test::SingleThreadTaskEnvironment task_environment_{ |
| test::SingleThreadTaskEnvironment::MainThreadType::IO}; |
| TestComponentContextForProcess test_context; |
| FidlErrorEventProcessExiter<base_testfidl::TestInterface> event_handler; |
| auto client_end = fuchsia_component::ConnectAt<base_testfidl::TestInterface>( |
| test_context.published_services_natural()); |
| EXPECT_TRUE(client_end.is_ok()); |
| fidl::Client client(std::move(*client_end), async_get_default_dispatcher(), |
| &event_handler); |
| |
| auto bind_and_close_service = [&]() { |
| { |
| TestInterfaceNaturalImpl test_service; |
| ScopedNaturalServiceBinding<base_testfidl::TestInterface> binding( |
| ComponentContextForProcess()->outgoing().get(), &test_service); |
| |
| ASSERT_EQ(ZX_OK, VerifyTestInterface(client)); |
| } |
| base::RunLoop().RunUntilIdle(); |
| }; |
| |
| EXPECT_DEATH( |
| bind_and_close_service(), |
| testing::HasSubstr("base.testfidl.TestInterface disconnected " |
| "unexpectedly, exiting: ZX_ERR_PEER_CLOSED (-24)")); |
| } |
| |
| TEST_F(FidlEventHandlerTest, FidlErrorEventHandler) { |
| RunLoop loop; |
| FidlErrorEventHandler<base_testfidl::TestInterface> event_handler( |
| base::BindLambdaForTesting( |
| [quit_closure = loop.QuitClosure()](fidl::UnbindInfo error) { |
| ASSERT_TRUE(error.is_peer_closed()); |
| quit_closure.Run(); |
| })); |
| |
| event_handler.on_fidl_error(fidl::UnbindInfo::PeerClosed(ZX_ERR_PEER_CLOSED)); |
| |
| loop.Run(); |
| } |
| |
| TEST_F(FidlEventHandlerTest, FidlErrorEventHandler_FiresOnServiceClosure) { |
| RunLoop loop; |
| FidlErrorEventHandler<base_testfidl::TestInterface> event_handler( |
| base::BindLambdaForTesting( |
| [quit_closure = loop.QuitClosure()](fidl::UnbindInfo error) { |
| ASSERT_TRUE(error.is_peer_closed()); |
| quit_closure.Run(); |
| })); |
| |
| auto client_end = fuchsia_component::ConnectAt<base_testfidl::TestInterface>( |
| test_context_.published_services_natural()); |
| EXPECT_TRUE(client_end.is_ok()); |
| fidl::Client client(std::move(*client_end), async_get_default_dispatcher(), |
| &event_handler); |
| |
| { |
| ScopedNaturalServiceBinding<base_testfidl::TestInterface> binding( |
| ComponentContextForProcess()->outgoing().get(), &test_service_); |
| |
| ASSERT_EQ(ZX_OK, VerifyTestInterface(client)); |
| }; |
| |
| loop.Run(); |
| } |
| |
| } // namespace base |