175 lines
6.4 KiB
C++
175 lines
6.4 KiB
C++
// 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/scoped_service_binding.h"
|
|
|
|
#include <lib/async/default.h>
|
|
#include <lib/sys/cpp/component_context.h>
|
|
|
|
#include "base/fuchsia/process_context.h"
|
|
#include "base/fuchsia/test_component_context_for_process.h"
|
|
#include "base/fuchsia/test_interface_natural_impl.h"
|
|
#include "base/run_loop.h"
|
|
#include "base/strings/string_piece.h"
|
|
#include "base/test/bind.h"
|
|
#include "base/test/task_environment.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace base {
|
|
|
|
class ScopedNaturalServiceBindingTest : public testing::Test {
|
|
protected:
|
|
ScopedNaturalServiceBindingTest() = default;
|
|
~ScopedNaturalServiceBindingTest() override = default;
|
|
|
|
const base::test::SingleThreadTaskEnvironment task_environment_{
|
|
base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
|
|
|
|
TestComponentContextForProcess test_context_;
|
|
TestInterfaceNaturalImpl test_service_;
|
|
};
|
|
|
|
// Verifies that ScopedNaturalServiceBinding allows more than one simultaneous
|
|
// client.
|
|
TEST_F(ScopedNaturalServiceBindingTest, ConnectTwice) {
|
|
ScopedNaturalServiceBinding<base_testfidl::TestInterface> binding(
|
|
ComponentContextForProcess()->outgoing().get(), &test_service_);
|
|
|
|
auto stub =
|
|
CreateTestInterfaceClient(test_context_.published_services_natural());
|
|
auto stub2 =
|
|
CreateTestInterfaceClient(test_context_.published_services_natural());
|
|
EXPECT_EQ(VerifyTestInterface(stub), ZX_OK);
|
|
EXPECT_EQ(VerifyTestInterface(stub2), ZX_OK);
|
|
}
|
|
|
|
// Verifies that ScopedNaturalServiceBinding allows more than one simultaneous
|
|
// client with a non-default discovery name.
|
|
TEST_F(ScopedNaturalServiceBindingTest, ConnectTwiceNameOverride) {
|
|
const char kInterfaceName[] = "fuchsia.TestInterface2";
|
|
|
|
ScopedNaturalServiceBinding<base_testfidl::TestInterface> new_service_binding(
|
|
ComponentContextForProcess()->outgoing().get(), &test_service_,
|
|
kInterfaceName);
|
|
|
|
auto stub = CreateTestInterfaceClient(
|
|
test_context_.published_services_natural(), kInterfaceName);
|
|
auto stub2 = CreateTestInterfaceClient(
|
|
test_context_.published_services_natural(), kInterfaceName);
|
|
EXPECT_EQ(VerifyTestInterface(stub), ZX_OK);
|
|
EXPECT_EQ(VerifyTestInterface(stub2), ZX_OK);
|
|
}
|
|
|
|
// Verify that we can publish a debug `TestInterface` service.
|
|
TEST_F(ScopedNaturalServiceBindingTest, ConnectDebugService) {
|
|
vfs::PseudoDir* const debug_dir =
|
|
ComponentContextForProcess()->outgoing()->debug_dir();
|
|
|
|
// Publish the test service to the "debug" directory.
|
|
ScopedNaturalServiceBinding<base_testfidl::TestInterface>
|
|
debug_service_binding(debug_dir, &test_service_);
|
|
|
|
// Connect a `ClientEnd` to the "debug" subdirectory.
|
|
auto debug_directory_endpoints =
|
|
fidl::CreateEndpoints<fuchsia_io::Directory>();
|
|
ASSERT_TRUE(debug_directory_endpoints.is_ok())
|
|
<< debug_directory_endpoints.status_string();
|
|
debug_dir->Serve(fuchsia::io::OpenFlags::RIGHT_READABLE |
|
|
fuchsia::io::OpenFlags::RIGHT_WRITABLE,
|
|
debug_directory_endpoints->server.TakeChannel());
|
|
|
|
// Attempt to connect via the "debug" directory.
|
|
auto debug_stub =
|
|
CreateTestInterfaceClient(std::move(debug_directory_endpoints->client));
|
|
EXPECT_EQ(VerifyTestInterface(debug_stub), ZX_OK);
|
|
|
|
// Verify that the `TestInterface` service does not appear in the outgoing
|
|
// service directory.
|
|
auto release_stub =
|
|
CreateTestInterfaceClient(test_context_.published_services_natural());
|
|
EXPECT_EQ(VerifyTestInterface(release_stub), ZX_ERR_PEER_CLOSED);
|
|
}
|
|
|
|
// Test the last client callback is called every time the number of active
|
|
// clients reaches 0.
|
|
TEST_F(ScopedNaturalServiceBindingTest, MultipleLastClientCallback) {
|
|
ScopedNaturalServiceBinding<base_testfidl::TestInterface> binding(
|
|
ComponentContextForProcess()->outgoing().get(), &test_service_);
|
|
int disconnect_count = 0;
|
|
binding.SetOnLastClientCallback(
|
|
BindLambdaForTesting([&disconnect_count]() { ++disconnect_count; }));
|
|
|
|
// Connect a client, verify it is functional.
|
|
{
|
|
auto stub =
|
|
CreateTestInterfaceClient(test_context_.published_services_natural());
|
|
EXPECT_EQ(VerifyTestInterface(stub), ZX_OK);
|
|
}
|
|
|
|
// Client disconnected on going out of scope, the callback should have been
|
|
// called once.
|
|
RunLoop().RunUntilIdle();
|
|
EXPECT_EQ(disconnect_count, 1);
|
|
|
|
// Connect another client, verify it is functional.
|
|
{
|
|
auto stub =
|
|
CreateTestInterfaceClient(test_context_.published_services_natural());
|
|
EXPECT_EQ(VerifyTestInterface(stub), ZX_OK);
|
|
}
|
|
|
|
// Client disconnected on going out of scope, the callback should have been
|
|
// called a second time.
|
|
RunLoop().RunUntilIdle();
|
|
EXPECT_EQ(disconnect_count, 2);
|
|
}
|
|
|
|
// Test the last client callback is called every time the number of active
|
|
// clients reaches 0.
|
|
TEST_F(ScopedNaturalServiceBindingTest, LastClientCallbackOnlyForLastClient) {
|
|
ScopedNaturalServiceBinding<base_testfidl::TestInterface> binding(
|
|
ComponentContextForProcess()->outgoing().get(), &test_service_);
|
|
int disconnect_count = 0;
|
|
binding.SetOnLastClientCallback(
|
|
BindLambdaForTesting([&disconnect_count]() { ++disconnect_count; }));
|
|
|
|
{
|
|
// Connect a long lived client, verify it is functional.
|
|
auto long_lived_stub =
|
|
CreateTestInterfaceClient(test_context_.published_services_natural());
|
|
EXPECT_EQ(VerifyTestInterface(long_lived_stub), ZX_OK);
|
|
|
|
// Connect a client, verify it is functional.
|
|
{
|
|
auto stub =
|
|
CreateTestInterfaceClient(test_context_.published_services_natural());
|
|
EXPECT_EQ(VerifyTestInterface(stub), ZX_OK);
|
|
}
|
|
|
|
// Client disconnected on going out of scope, the callback should not have
|
|
// been called because the long-lived client is still connected.
|
|
RunLoop().RunUntilIdle();
|
|
EXPECT_EQ(disconnect_count, 0);
|
|
|
|
// Connect another client, verify it is functional.
|
|
{
|
|
auto stub =
|
|
CreateTestInterfaceClient(test_context_.published_services_natural());
|
|
EXPECT_EQ(VerifyTestInterface(stub), ZX_OK);
|
|
}
|
|
|
|
// Client disconnected on going out of scope, the callback should not have
|
|
// been called because the long-lived client is still connected.
|
|
RunLoop().RunUntilIdle();
|
|
EXPECT_EQ(disconnect_count, 0);
|
|
}
|
|
|
|
// Long lived client disconnected on going out of scope, the callback should
|
|
// have been called a third time.
|
|
RunLoop().RunUntilIdle();
|
|
EXPECT_EQ(disconnect_count, 1);
|
|
}
|
|
|
|
} // namespace base
|