blob: 188db560f65ba72422ea9c9a4385f9cf19039f3a [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 <fidl/fidl.test.compatibility/cpp/wire.h>
#include <fidl/fidl.test.compatibility/cpp/wire_test_base.h>
#include <fidl/fidl.test.compatibility/cpp/wire_types.h>
#include <fidl/fidl.test.imported/cpp/wire.h>
#include <fidl/fidl.test.imported/cpp/wire_types.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/sys/cpp/component_context.h>
#include <zircon/status.h>
#include <cstdlib>
#include <iostream>
#include <optional>
#include <string>
constexpr const char kEchoInterfaceName[] = "fidl.test.compatibility.Echo";
using namespace fidl_test_compatibility;
class EchoClientApp {
public:
EchoClientApp(::fidl::StringView server_url)
: context_(sys::ComponentContext::CreateAndServeOutgoingDirectory()),
client_(fidl::WireSyncClient<Echo>(ConnectTo(server_url))) {}
// Half the methods are testing the managed flavor; the other half are testing caller-allocate.
fidl::WireResult<Echo::EchoMinimal> EchoMinimal(::fidl::StringView forward_to_server) {
return client_->EchoMinimal(std::move(forward_to_server));
}
fidl::WireResult<Echo::EchoMinimalWithError> EchoMinimalWithError(
::fidl::StringView forward_to_server, wire::RespondWith result_variant) {
return client_->EchoMinimalWithError(std::move(forward_to_server), result_variant);
}
fidl::Status EchoMinimalNoRetVal(::fidl::StringView forward_to_server,
fidl::WireSyncEventHandler<Echo>& event_handler) {
auto result = client_->EchoMinimalNoRetVal(std::move(forward_to_server));
if (!result.ok()) {
return result;
}
return client_.HandleOneEvent(event_handler);
}
fidl::WireResult<Echo::EchoStruct> EchoStruct(wire::Struct value,
::fidl::StringView forward_to_server) {
return client_->EchoStruct(std::move(value), std::move(forward_to_server));
}
fidl::WireResult<Echo::EchoNamedStruct> EchoNamedStruct(
fidl_test_imported::wire::SimpleStruct value, ::fidl::StringView forward_to_server) {
return client_->EchoNamedStruct(std::move(value), std::move(forward_to_server));
}
fidl::WireResult<Echo::EchoNamedStructWithError> EchoNamedStructWithError(
fidl_test_imported::wire::SimpleStruct value, uint32_t err,
::fidl::StringView forward_to_server, fidl_test_imported::wire::WantResponse result_variant) {
return client_->EchoNamedStructWithError(std::move(value), err, std::move(forward_to_server),
result_variant);
}
fidl::Status EchoNamedStructNoRetVal(fidl_test_imported::wire::SimpleStruct value,
::fidl::StringView forward_to_server,
fidl::WireSyncEventHandler<Echo>& event_handler) {
auto result = client_->EchoNamedStructNoRetVal(std::move(value), std::move(forward_to_server));
if (!result.ok()) {
return result;
}
return client_.HandleOneEvent(event_handler);
}
fidl::WireResult<Echo::EchoStructWithError> EchoStructWithError(
wire::Struct value, wire::DefaultEnum err, ::fidl::StringView forward_to_server,
wire::RespondWith result_variant) {
return client_->EchoStructWithError(std::move(value), err, std::move(forward_to_server),
result_variant);
}
fidl::Status EchoStructNoRetVal(wire::Struct value, ::fidl::StringView forward_to_server,
fidl::WireSyncEventHandler<Echo>& event_handler) {
auto result = client_->EchoStructNoRetVal(std::move(value), std::move(forward_to_server));
if (!result.ok()) {
return result;
}
return client_.HandleOneEvent(event_handler);
}
fidl::WireUnownedResult<Echo::EchoArrays> EchoArrays(::fidl::BufferSpan buffer,
wire::ArraysStruct value,
::fidl::StringView forward_to_server) {
return client_.buffer(buffer)->EchoArrays(std::move(value), forward_to_server);
}
fidl::WireResult<Echo::EchoArraysWithError> EchoArraysWithError(
wire::ArraysStruct value, wire::DefaultEnum err, ::fidl::StringView forward_to_server,
wire::RespondWith result_variant) {
return client_->EchoArraysWithError(std::move(value), err, std::move(forward_to_server),
result_variant);
}
fidl::WireResult<Echo::EchoVectors> EchoVectors(wire::VectorsStruct value,
::fidl::StringView forward_to_server) {
return client_->EchoVectors(std::move(value), std::move(forward_to_server));
}
fidl::WireResult<Echo::EchoVectorsWithError> EchoVectorsWithError(
wire::VectorsStruct value, wire::DefaultEnum err, ::fidl::StringView forward_to_server,
wire::RespondWith result_variant) {
return client_->EchoVectorsWithError(std::move(value), err, std::move(forward_to_server),
result_variant);
}
fidl::WireUnownedResult<Echo::EchoTable> EchoTable(::fidl::BufferSpan buffer,
wire::AllTypesTable value,
::fidl::StringView forward_to_server) {
return client_.buffer(buffer)->EchoTable(value, forward_to_server);
}
fidl::WireUnownedResult<Echo::EchoTableWithError> EchoTableWithError(
::fidl::BufferSpan buffer, wire::AllTypesTable value, wire::DefaultEnum err,
::fidl::StringView forward_to_server, wire::RespondWith result_variant) {
return client_.buffer(buffer)->EchoTableWithError(value, err, forward_to_server,
result_variant);
}
fidl::WireResult<Echo::EchoXunions> EchoXunions(::fidl::VectorView<wire::AllTypesXunion> value,
::fidl::StringView forward_to_server) {
return client_->EchoXunions(std::move(value), std::move(forward_to_server));
}
fidl::WireResult<Echo::EchoXunionsWithError> EchoXunionsWithError(
::fidl::VectorView<wire::AllTypesXunion> value, wire::DefaultEnum err,
::fidl::StringView forward_to_server, wire::RespondWith result_variant) {
return client_->EchoXunionsWithError(std::move(value), err, std::move(forward_to_server),
result_variant);
}
fidl::WireResult<Echo::EchoTablePayload> EchoTablePayload(
fidl_test_compatibility::wire::RequestTable payload) {
return client_->EchoTablePayload(std::move(payload));
}
fidl::WireResult<Echo::EchoTablePayloadWithError> EchoTablePayloadWithError(
fidl_test_compatibility::wire::EchoEchoTablePayloadWithErrorRequest payload) {
return client_->EchoTablePayloadWithError(std::move(payload));
}
fidl::Status EchoTablePayloadNoRetVal(fidl_test_compatibility::wire::RequestTable payload,
fidl::WireSyncEventHandler<Echo>& event_handler) {
auto result = client_->EchoTablePayloadNoRetVal(std::move(payload));
if (!result.ok()) {
return result;
}
return client_.HandleOneEvent(event_handler);
}
fidl::WireResult<Echo::EchoTableRequestComposed> EchoTableRequestComposed(
::fidl_test_imported::wire::ComposedEchoTableRequestComposedRequest payload) {
return client_->EchoTableRequestComposed(std::move(payload));
}
fidl::WireResult<Echo::EchoUnionPayload> EchoUnionPayload(
fidl_test_compatibility::wire::RequestUnion payload) {
return client_->EchoUnionPayload(std::move(payload));
}
fidl::WireResult<Echo::EchoUnionPayloadWithError> EchoUnionPayloadWithError(
fidl_test_compatibility::wire::EchoEchoUnionPayloadWithErrorRequest payload) {
return client_->EchoUnionPayloadWithError(std::move(payload));
}
fidl::Status EchoUnionPayloadNoRetVal(fidl_test_compatibility::wire::RequestUnion payload,
fidl::WireSyncEventHandler<Echo>& event_handler) {
auto result = client_->EchoUnionPayloadNoRetVal(std::move(payload));
if (!result.ok()) {
return result;
}
return client_.HandleOneEvent(event_handler);
}
fidl::WireResult<Echo::EchoUnionResponseWithErrorComposed> EchoUnionResponseWithErrorComposed(
int64_t value, bool want_absolute_value, ::fidl::StringView forward_to_server,
uint32_t result_err, fidl_test_imported::wire::WantResponse result_variant) {
return client_->EchoUnionResponseWithErrorComposed(
value, want_absolute_value, forward_to_server, result_err, result_variant);
}
EchoClientApp(const EchoClientApp&) = delete;
EchoClientApp& operator=(const EchoClientApp&) = delete;
private:
// Called once upon construction to launch and connect to the server.
::fidl::ClientEnd<fidl_test_compatibility::Echo> ConnectTo(::fidl::StringView server_url) {
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = std::string(server_url.data(), server_url.size());
echo_provider_ = sys::ServiceDirectory::CreateWithRequest(&launch_info.directory_request);
fuchsia::sys::LauncherPtr launcher;
context_->svc()->Connect(launcher.NewRequest());
launcher->CreateComponent(std::move(launch_info), controller_.NewRequest());
auto echo_ends = ::fidl::CreateEndpoints<fidl_test_compatibility::Echo>();
ZX_ASSERT(echo_ends.is_ok());
ZX_ASSERT(echo_provider_->Connect(kEchoInterfaceName, echo_ends->server.TakeChannel()) ==
ZX_OK);
return std::move(echo_ends->client);
}
std::unique_ptr<sys::ComponentContext> context_;
std::shared_ptr<sys::ServiceDirectory> echo_provider_;
fuchsia::sys::ComponentControllerPtr controller_;
fidl::WireSyncClient<Echo> client_;
};
class EchoSyncEventHandlerTestStub : public fidl::testing::WireSyncEventHandlerTestBase<Echo> {
public:
void NotImplemented_(const std::string& name) final { ZX_PANIC("Unexpected %s", name.c_str()); }
};
class EchoConnection final : public fidl::WireServer<Echo> {
public:
EchoConnection() = default;
void EchoMinimal(EchoMinimalRequestView request, EchoMinimalCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
completer.Reply();
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoMinimal("");
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
completer.Reply();
}
}
void EchoMinimalWithError(EchoMinimalWithErrorRequestView request,
EchoMinimalWithErrorCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
if (request->result_variant == wire::RespondWith::kErr) {
completer.ReplyError(0u);
} else {
completer.ReplySuccess();
}
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoMinimalWithError("", request->result_variant);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess();
}
}
}
void EchoMinimalNoRetVal(EchoMinimalNoRetValRequestView request,
EchoMinimalNoRetValCompleter::Sync&) override {
if (request->forward_to_server.empty()) {
fidl::Status result = fidl::WireSendEvent(server_binding_.value())->EchoMinimalEvent();
ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s",
result.FormatDescription().c_str());
} else {
class EventHandler : public EchoSyncEventHandlerTestStub {
public:
explicit EventHandler(EchoConnection* connection) : connection_(connection) {}
fidl::Status result() const { return result_; }
void EchoMinimalEvent(fidl::WireEvent<Echo::EchoMinimalEvent>* event) override {
result_ = fidl::WireSendEvent(connection_->server_binding_.value())->EchoMinimalEvent();
}
private:
EchoConnection* const connection_;
fidl::Status result_ = fidl::Status::Ok();
};
EchoClientApp app(request->forward_to_server);
EventHandler event_handler(this);
fidl::Status status = app.EchoMinimalNoRetVal("", event_handler);
ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s",
status.FormatDescription().c_str());
ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s",
event_handler.result().FormatDescription().c_str());
}
}
void EchoStruct(EchoStructRequestView request, EchoStructCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
completer.Reply(std::move(request->value));
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoStruct(std::move(request->value), "");
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
completer.Reply(std::move(result->value));
}
}
void EchoStructWithError(EchoStructWithErrorRequestView request,
EchoStructWithErrorCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
if (request->result_variant == wire::RespondWith::kErr) {
completer.ReplyError(request->result_err);
} else {
completer.ReplySuccess(std::move(request->value));
}
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoStructWithError(std::move(request->value), request->result_err, "",
request->result_variant);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess(std::move(result.value().value()->value));
}
}
}
void EchoStructNoRetVal(EchoStructNoRetValRequestView request,
EchoStructNoRetValCompleter::Sync&) override {
if (request->forward_to_server.empty()) {
fidl::Status result =
fidl::WireSendEvent(server_binding_.value())->EchoEvent(std::move(request->value));
ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s",
result.FormatDescription().c_str());
} else {
class EventHandler : public EchoSyncEventHandlerTestStub {
public:
explicit EventHandler(EchoConnection* connection) : connection_(connection) {}
fidl::Status result() const { return result_; }
void EchoEvent(fidl::WireEvent<Echo::EchoEvent>* event) override {
result_ = fidl::WireSendEvent(connection_->server_binding_.value())
->EchoEvent(std::move(event->value));
}
private:
EchoConnection* const connection_;
fidl::Status result_ = fidl::Status::Ok();
};
EchoClientApp app(request->forward_to_server);
EventHandler event_handler(this);
fidl::Status status = app.EchoStructNoRetVal(std::move(request->value), "", event_handler);
ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s",
status.FormatDescription().c_str());
ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s",
event_handler.result().FormatDescription().c_str());
}
}
void EchoArrays(EchoArraysRequestView request, EchoArraysCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
completer.Reply(std::move(request->value));
} else {
fidl::SyncClientBuffer<Echo::EchoArrays> buffer;
EchoClientApp app(request->forward_to_server);
auto result = app.EchoArrays(buffer.view(), std::move(request->value), "");
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
completer.Reply(std::move(result->value));
}
}
void EchoArraysWithError(EchoArraysWithErrorRequestView request,
EchoArraysWithErrorCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
if (request->result_variant == wire::RespondWith::kErr) {
completer.ReplyError(request->result_err);
} else {
completer.ReplySuccess(std::move(request->value));
}
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoArraysWithError(std::move(request->value), request->result_err, "",
request->result_variant);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s: %s",
zx_status_get_string(result.status()), result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess(std::move(result.value().value()->value));
}
}
}
void EchoVectors(EchoVectorsRequestView request, EchoVectorsCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
completer.Reply(std::move(request->value));
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoVectors(std::move(request->value), "");
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s: %s",
zx_status_get_string(result.status()), result.FormatDescription().c_str());
completer.Reply(std::move(result->value));
}
}
void EchoVectorsWithError(EchoVectorsWithErrorRequestView request,
EchoVectorsWithErrorCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
if (request->result_variant == wire::RespondWith::kErr) {
completer.ReplyError(request->result_err);
} else {
completer.ReplySuccess(std::move(request->value));
}
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoVectorsWithError(std::move(request->value), request->result_err, "",
request->result_variant);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s: %s",
zx_status_get_string(result.status()), result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess(std::move(result.value().value()->value));
}
}
}
void EchoTable(EchoTableRequestView request, EchoTableCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
completer.Reply(request->value);
} else {
fidl::SyncClientBuffer<Echo::EchoTable> buffer;
EchoClientApp app(request->forward_to_server);
auto result = app.EchoTable(buffer.view(), request->value, "");
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s: %s",
zx_status_get_string(result.status()), result.FormatDescription().c_str());
completer.Reply(result->value);
}
}
void EchoTableWithError(EchoTableWithErrorRequestView request,
EchoTableWithErrorCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
if (request->result_variant == wire::RespondWith::kErr) {
completer.ReplyError(request->result_err);
} else {
completer.ReplySuccess(request->value);
}
} else {
fidl::SyncClientBuffer<Echo::EchoTableWithError> buffer;
EchoClientApp app(request->forward_to_server);
auto result = app.EchoTableWithError(buffer.view(), request->value, request->result_err, "",
request->result_variant);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s: %s",
zx_status_get_string(result.status()), result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess(std::move(result.value().value()->value));
}
}
}
void EchoXunions(EchoXunionsRequestView request, EchoXunionsCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
completer.Reply(std::move(request->value));
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoXunions(std::move(request->value), "");
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s: %s",
zx_status_get_string(result.status()), result.FormatDescription().c_str());
completer.Reply(std::move(result->value));
}
}
void EchoXunionsWithError(EchoXunionsWithErrorRequestView request,
EchoXunionsWithErrorCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
if (request->result_variant == wire::RespondWith::kErr) {
completer.ReplyError(request->result_err);
} else {
completer.ReplySuccess(std::move(request->value));
}
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoXunionsWithError(std::move(request->value), request->result_err, "",
request->result_variant);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s: %s",
zx_status_get_string(result.status()), result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess(std::move(result.value().value()->value));
}
}
}
void EchoNamedStruct(EchoNamedStructRequestView request,
EchoNamedStructCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
completer.Reply(std::move(request->value));
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoNamedStruct(std::move(request->value), "");
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
completer.Reply(std::move(result->value));
}
}
void EchoNamedStructWithError(EchoNamedStructWithErrorRequestView request,
EchoNamedStructWithErrorCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
if (request->result_variant == fidl_test_imported::wire::WantResponse::kErr) {
completer.ReplyError(request->result_err);
} else {
completer.ReplySuccess(std::move(request->value));
}
} else {
EchoClientApp app(request->forward_to_server);
auto result = app.EchoNamedStructWithError(std::move(request->value), request->result_err, "",
request->result_variant);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess(std::move(result.value().value()->value));
}
}
}
void EchoNamedStructNoRetVal(EchoNamedStructNoRetValRequestView request,
EchoNamedStructNoRetValCompleter::Sync&) override {
if (request->forward_to_server.empty()) {
fidl::Status result =
fidl::WireSendEvent(server_binding_.value())->OnEchoNamedEvent(std::move(request->value));
ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s",
result.FormatDescription().c_str());
} else {
class EventHandler : public EchoSyncEventHandlerTestStub {
public:
explicit EventHandler(EchoConnection* connection) : connection_(connection) {}
fidl::Status result() const { return result_; }
void OnEchoNamedEvent(fidl::WireEvent<Echo::OnEchoNamedEvent>* event) override {
result_ = fidl::WireSendEvent(connection_->server_binding_.value())
->OnEchoNamedEvent(std::move(event->value));
}
private:
EchoConnection* const connection_;
fidl::Status result_ = fidl::Status::Ok();
};
EchoClientApp app(request->forward_to_server);
EventHandler event_handler(this);
fidl::Status status = app.EchoNamedStructNoRetVal(request->value, "", event_handler);
ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s",
status.FormatDescription().c_str());
ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s",
event_handler.result().FormatDescription().c_str());
}
}
void EchoTablePayload(EchoTablePayloadRequestView request,
EchoTablePayloadCompleter::Sync& completer) override {
if (!request->has_forward_to_server()) {
fidl::Arena allocator;
completer.Reply(fidl_test_compatibility::wire::ResponseTable::Builder(allocator)
.value(request->value())
.Build());
} else {
EchoClientApp app(request->forward_to_server());
fidl::Arena allocator;
;
auto result =
app.EchoTablePayload(fidl_test_compatibility::wire::RequestTable::Builder(allocator)
.value(request->value())
.Build());
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
completer.Reply(std::move(*result.Unwrap()));
}
}
void EchoTablePayloadWithError(EchoTablePayloadWithErrorRequestView request,
EchoTablePayloadWithErrorCompleter::Sync& completer) override {
if (!request->has_forward_to_server()) {
if (request->result_variant() == wire::RespondWith::kErr) {
completer.ReplyError(request->result_err());
} else {
fidl::Arena allocator;
wire::EchoEchoTablePayloadWithErrorResult res =
wire::EchoEchoTablePayloadWithErrorResult::WithResponse(
allocator, wire::ResponseTable::Builder(allocator).value(request->value()).Build());
completer.Reply(::fitx::ok(&res.response()));
}
} else {
EchoClientApp app(request->forward_to_server());
fidl::Arena allocator;
auto builder = wire::EchoEchoTablePayloadWithErrorRequest::Builder(allocator);
builder.result_variant(request->result_variant());
if (request->result_variant() == wire::RespondWith::kErr) {
builder.result_err(request->result_err());
} else {
builder.value(request->value());
}
auto result = app.EchoTablePayloadWithError(builder.Build());
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess(*result.value().value());
}
}
}
void EchoTablePayloadNoRetVal(EchoTablePayloadNoRetValRequestView request,
EchoTablePayloadNoRetValCompleter::Sync&) override {
if (!request->has_forward_to_server()) {
fidl::Arena allocator;
fidl::Status result =
fidl::WireSendEvent(server_binding_.value())
->OnEchoTablePayloadEvent(
wire::ResponseTable::Builder(allocator).value(request->value()).Build());
ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s",
result.FormatDescription().c_str());
} else {
class EventHandler : public EchoSyncEventHandlerTestStub {
public:
explicit EventHandler(EchoConnection* connection) : connection_(connection) {}
fidl::Status result() const { return result_; }
void OnEchoTablePayloadEvent(
fidl::WireEvent<Echo::OnEchoTablePayloadEvent>* event) override {
result_ = fidl::WireSendEvent(connection_->server_binding_.value())
->OnEchoTablePayloadEvent(*event);
}
private:
EchoConnection* const connection_;
fidl::Status result_ = fidl::Status::Ok();
};
EchoClientApp app(request->forward_to_server());
EventHandler event_handler(this);
fidl::Arena allocator;
fidl::Status status = app.EchoTablePayloadNoRetVal(
wire::RequestTable::Builder(allocator).value(request->value()).Build(), event_handler);
ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s",
status.FormatDescription().c_str());
ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s",
event_handler.result().FormatDescription().c_str());
}
}
void EchoTableRequestComposed(EchoTableRequestComposedRequestView request,
EchoTableRequestComposedCompleter::Sync& completer) override {
if (!request->has_forward_to_server()) {
completer.Reply(
std::move(fidl_test_imported::wire::SimpleStruct{.f1 = true, .f2 = request->value()}));
} else {
EchoClientApp app(request->forward_to_server());
fidl::Arena allocator;
auto result = app.EchoTableRequestComposed(
fidl_test_imported::wire::ComposedEchoTableRequestComposedRequest::Builder(allocator)
.value(request->value())
.Build());
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
completer.Reply(std::move(result->value));
}
}
void EchoUnionPayload(EchoUnionPayloadRequestView request,
EchoUnionPayloadCompleter::Sync& completer) override {
fidl::StringView& forward_to_server = request->is_signed_()
? request->signed_().forward_to_server
: request->unsigned_().forward_to_server;
if (forward_to_server.empty()) {
fidl::Arena allocator;
fidl_test_compatibility::wire::ResponseUnion resp;
if (request->is_signed_()) {
resp = fidl_test_compatibility::wire::ResponseUnion::WithSigned_(allocator,
request->signed_().value);
} else {
resp = fidl_test_compatibility::wire::ResponseUnion::WithUnsigned_(
allocator, request->unsigned_().value);
}
completer.Reply(std::move(resp));
} else {
EchoClientApp app(forward_to_server);
fidl::Arena allocator;
fidl_test_compatibility::wire::RequestUnion req;
if (request->is_signed_()) {
req =
fidl_test_compatibility::wire::RequestUnion::WithSigned_(allocator, request->signed_());
req.signed_().forward_to_server = "";
} else {
req = fidl_test_compatibility::wire::RequestUnion::WithUnsigned_(allocator,
request->unsigned_());
req.unsigned_().forward_to_server = "";
}
auto result = app.EchoUnionPayload(req);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
completer.Reply(std::move(*result.Unwrap()));
}
}
void EchoUnionPayloadWithError(EchoUnionPayloadWithErrorRequestView request,
EchoUnionPayloadWithErrorCompleter::Sync& completer) override {
fidl::StringView& forward_to_server = request->is_signed_()
? request->signed_().forward_to_server
: request->unsigned_().forward_to_server;
wire::RespondWith& result_variant = request->is_signed_() ? request->signed_().result_variant
: request->unsigned_().result_variant;
if (forward_to_server.empty()) {
if (result_variant == wire::RespondWith::kErr) {
completer.ReplyError(request->is_signed_() ? request->signed_().result_err
: request->unsigned_().result_err);
} else {
fidl::Arena allocator;
fidl_test_compatibility::wire::ResponseUnion resp;
if (request->is_signed_()) {
resp = fidl_test_compatibility::wire::ResponseUnion::WithSigned_(
allocator, request->signed_().value);
} else {
resp = fidl_test_compatibility::wire::ResponseUnion::WithUnsigned_(
allocator, request->unsigned_().value);
}
completer.ReplySuccess(resp);
}
} else {
EchoClientApp app(forward_to_server);
fidl::Arena allocator;
fidl_test_compatibility::wire::EchoEchoUnionPayloadWithErrorRequest req;
if (request->is_signed_()) {
req = fidl_test_compatibility::wire::EchoEchoUnionPayloadWithErrorRequest::WithSigned_(
allocator, request->signed_());
req.signed_().forward_to_server = "";
} else {
req = fidl_test_compatibility::wire::EchoEchoUnionPayloadWithErrorRequest::WithUnsigned_(
allocator, request->unsigned_());
req.unsigned_().forward_to_server = "";
}
auto result = app.EchoUnionPayloadWithError(req);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess(*result.value().value());
}
}
}
void EchoUnionPayloadNoRetVal(EchoUnionPayloadNoRetValRequestView request,
EchoUnionPayloadNoRetValCompleter::Sync&) override {
fidl::StringView& forward_to_server = request->is_signed_()
? request->signed_().forward_to_server
: request->unsigned_().forward_to_server;
if (forward_to_server.empty()) {
fidl::Arena allocator;
fidl_test_compatibility::wire::ResponseUnion resp;
if (request->is_signed_()) {
resp = fidl_test_compatibility::wire::ResponseUnion::WithSigned_(allocator,
request->signed_().value);
} else {
resp = fidl_test_compatibility::wire::ResponseUnion::WithUnsigned_(
allocator, request->unsigned_().value);
}
fidl::Status result =
fidl::WireSendEvent(server_binding_.value())->OnEchoUnionPayloadEvent(std::move(resp));
ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s",
result.FormatDescription().c_str());
} else {
class EventHandler : public EchoSyncEventHandlerTestStub {
public:
explicit EventHandler(EchoConnection* connection) : connection_(connection) {}
fidl::Status result() const { return result_; }
void OnEchoUnionPayloadEvent(
fidl::WireEvent<Echo::OnEchoUnionPayloadEvent>* event) override {
result_ = fidl::WireSendEvent(connection_->server_binding_.value())
->OnEchoUnionPayloadEvent(*event);
}
private:
EchoConnection* const connection_;
fidl::Status result_ = fidl::Status::Ok();
};
EchoClientApp app(forward_to_server);
EventHandler event_handler(this);
fidl::Arena allocator;
fidl_test_compatibility::wire::RequestUnion req;
if (request->is_signed_()) {
req =
fidl_test_compatibility::wire::RequestUnion::WithSigned_(allocator, request->signed_());
req.signed_().forward_to_server = "";
} else {
req = fidl_test_compatibility::wire::RequestUnion::WithUnsigned_(allocator,
request->unsigned_());
req.unsigned_().forward_to_server = "";
}
fidl::Status status = app.EchoUnionPayloadNoRetVal(req, event_handler);
ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s",
status.FormatDescription().c_str());
ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s",
event_handler.result().FormatDescription().c_str());
}
}
void EchoUnionResponseWithErrorComposed(
EchoUnionResponseWithErrorComposedRequestView request,
EchoUnionResponseWithErrorComposedCompleter::Sync& completer) override {
if (request->forward_to_server.empty()) {
if (request->result_variant == fidl_test_imported::wire::WantResponse::kErr) {
completer.ReplyError(request->result_err);
return;
}
fidl::Arena allocator;
fidl_test_imported::wire::ComposedEchoUnionResponseWithErrorComposedResponse resp;
if (request->want_absolute_value) {
auto obj_view =
fidl::ObjectView<uint64_t>(allocator, static_cast<uint64_t>(std::abs(request->value)));
resp = fidl_test_imported::wire::ComposedEchoUnionResponseWithErrorComposedResponse::
WithUnsigned_(std::move(obj_view));
} else {
auto obj_view = fidl::ObjectView<int64_t>(allocator, request->value);
resp = fidl_test_imported::wire::ComposedEchoUnionResponseWithErrorComposedResponse::
WithSigned_(std::move(obj_view));
}
completer.ReplySuccess(resp);
} else {
EchoClientApp app(request->forward_to_server);
auto result =
app.EchoUnionResponseWithErrorComposed(request->value, request->want_absolute_value, "",
request->result_err, request->result_variant);
ZX_ASSERT_MSG(result.status() == ZX_OK, "Forwarding failed: %s",
result.FormatDescription().c_str());
if (result.value().is_error()) {
completer.ReplyError(result.value().error_value());
} else {
completer.ReplySuccess(*result.value().value());
}
}
}
void set_server_binding(::fidl::ServerBindingRef<Echo> binding) {
server_binding_.emplace(binding);
}
private:
std::optional<::fidl::ServerBindingRef<Echo>> server_binding_;
};
int main(int argc, const char** argv) {
// The FIDL support lib requires async_get_default_dispatcher() to return
// non-null.
async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
auto context = sys::ComponentContext::CreateAndServeOutgoingDirectory();
std::vector<std::unique_ptr<EchoConnection>> connections;
context->outgoing()->AddPublicService(
std::make_unique<vfs::Service>([&](zx::channel request, async_dispatcher_t* dispatcher) {
auto conn = std::make_unique<EchoConnection>();
auto binding = ::fidl::BindServer(
dispatcher, ::fidl::ServerEnd<fidl_test_compatibility::Echo>(std::move(request)),
conn.get());
conn->set_server_binding(std::move(binding));
connections.push_back(std::move(conn));
}),
kEchoInterfaceName);
loop.Run();
return EXIT_SUCCESS;
}