blob: 493ce57fa7d0cc846840498dca5725b7dce23264 [file] [log] [blame]
// Copyright 2021 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.
// [START import_statement_cpp]
#include <lib/sys/component/cpp/testing/realm_builder.h>
// [END import_statement_cpp]
#include <fidl/examples/routing/echo/cpp/fidl.h>
#include <fuchsia/component/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/dispatcher.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fidl/cpp/string.h>
#include <zircon/status.h>
#include <gtest/gtest.h>
#include <src/lib/testing/loop_fixture/real_loop_fixture.h>
// [START use_namespace_cpp]
// NOLINTNEXTLINE
using namespace component_testing;
// [END use_namespace_cpp]
class RealmBuilderTest : public ::gtest::RealLoopFixture {};
// This test demonstrates constructing a realm with two child components
// and verifying the `fidl.examples.routing.Echo` protocol.
TEST_F(RealmBuilderTest, RoutesFromEcho) {
// [START init_realm_builder_cpp]
auto builder = RealmBuilder::Create();
// [END init_realm_builder_cpp]
// [START add_component_cpp]
// [START add_server_cpp]
// Add component server to the realm, which is fetched using a URL.
builder.AddChild("echo_server",
"fuchsia-pkg://fuchsia.com/realm-builder-examples#meta/echo_server.cm");
// [END add_server_cpp]
// Add component to the realm, which is fetched using a fragment-only URL. The
// child is not exposing a service, so the `EAGER` option ensures the child
// starts when the realm is built.
builder.AddChild("echo_client", "#meta/echo_client.cm",
ChildOptions{.startup_mode = StartupMode::EAGER});
// [END add_component_cpp]
// [START route_between_children_cpp]
builder.AddRoute(Route{.capabilities = {Protocol{"fidl.examples.routing.echo.Echo"}},
.source = ChildRef{"echo_server"},
.targets = {ChildRef{"echo_client"}}});
// [END route_between_children_cpp]
// [START route_to_test_cpp]
builder.AddRoute(Route{.capabilities = {Protocol{"fidl.examples.routing.echo.Echo"}},
.source = ChildRef{"echo_server"},
.targets = {ParentRef()}});
// [END route_to_test_cpp]
// [START route_from_test_cpp]
builder.AddRoute(Route{.capabilities = {Protocol{"fuchsia.logger.LogSink"}},
.source = ParentRef(),
.targets = {ChildRef{"echo_server"}, ChildRef{"echo_client"}}});
// [END route_from_test_cpp]
// [START build_realm_cpp]
auto realm = builder.Build(dispatcher());
// [END build_realm_cpp]
// [START get_child_name_cpp]
std::cout << "Child Name: " << realm.component().GetChildName() << std::endl;
// [END get_child_name_cpp]
// [START call_echo_cpp]
auto echo = realm.component().ConnectSync<fidl::examples::routing::echo::Echo>();
fidl::StringPtr response;
echo->EchoString("hello", &response);
ASSERT_EQ(response, "hello");
// [END call_echo_cpp]
}
// [START mock_component_impl_cpp]
class LocalEchoServerImpl : public fidl::examples::routing::echo::Echo, public LocalComponentImpl {
public:
explicit LocalEchoServerImpl(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher) {}
// Override `OnStart` from `LocalComponentImpl` class.
void OnStart() override {
// When `OnStart()` is called, this implementation can call methods to
// access handles to the component's incoming capabilities (`ns()` and
// `svc()`) and outgoing capabilities (`outgoing()`).
ASSERT_EQ(outgoing()->AddPublicService(bindings_.GetHandler(this, dispatcher_)), ZX_OK);
}
// Override `EchoString` from `Echo` protocol.
void EchoString(::fidl::StringPtr value, EchoStringCallback callback) override {
callback(std::move(value));
}
private:
async_dispatcher_t* dispatcher_;
fidl::BindingSet<fidl::examples::routing::echo::Echo> bindings_;
};
// [END mock_component_impl_cpp]
// This test demonstrates constructing a realm with a mocked LocalComponent
// implementation of the `fidl.examples.routing.Echo` protocol.
TEST_F(RealmBuilderTest, RoutesFromMockEcho) {
auto builder = RealmBuilder::Create();
// [START add_mock_component_cpp]
// Add component to the realm, providing a mock implementation
builder.AddLocalChild("echo_server",
[&]() { return std::make_unique<LocalEchoServerImpl>(dispatcher()); });
// [END add_mock_component_cpp]
builder.AddRoute(Route{.capabilities = {Protocol{"fuchsia.logger.LogSink"}},
.source = ParentRef(),
.targets = {ChildRef{"echo_server"}}});
builder.AddRoute(Route{.capabilities = {Protocol{"fidl.examples.routing.echo.Echo"}},
.source = ChildRef{"echo_server"},
.targets = {ParentRef()}});
auto realm = builder.Build(dispatcher());
auto cleanup = fit::defer([&]() {
bool complete = false;
realm.Teardown([&](fit::result<fuchsia::component::Error> result) { complete = true; });
RunLoopUntil([&]() { return complete; });
});
auto echo = realm.component().Connect<fidl::examples::routing::echo::Echo>();
bool was_called = false;
echo->EchoString("hello", [&](const fidl::StringPtr& response) {
was_called = true;
ASSERT_EQ(response, "hello");
});
RunLoopUntil([&]() { return was_called; });
}