blob: 87bfe7121a88bffcff28343eaff1d89d4a93b9a0 [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.
#include <lib/async-loop/cpp/loop.h>
#include <lib/fidl/cpp/client.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <array>
#include <zxtest/zxtest.h>
#include "test_messages.h"
namespace {
class TestProtocol {
TestProtocol() = delete;
};
} // namespace
// Fake client implementations.
namespace fidl {
template <>
class AsyncEventHandler<TestProtocol> : public fidl::internal::AsyncEventHandler {};
namespace internal {
template <>
class WireClientImpl<TestProtocol> : public ClientBase {
public:
void SomeWireMethod() {
GoodMessage msg;
fidl::Result result = MakeSyncCallWith([&](std::shared_ptr<zx::channel> channel) {
zx_status_t status =
zx_channel_write_etc(channel->get(), 0, static_cast<void*>(msg.message().bytes().data()),
msg.message().bytes().actual(), msg.message().handles().data(),
msg.message().handles().actual());
EXPECT_OK(status);
return fidl::Result::Ok();
});
EXPECT_OK(result.status());
}
private:
std::optional<UnbindInfo> DispatchEvent(fidl::IncomingMessage& msg,
AsyncEventHandler* maybe_event_handler) override {
ZX_PANIC("Not used in this test");
}
};
template <>
class NaturalClientImpl<TestProtocol> : public NaturalClientBase {
public:
using NaturalClientBase::NaturalClientBase;
void SomeNaturalMethod() const {
GoodMessage msg;
fidl::Result result = messenger().OneWay(msg.type(), msg.message());
EXPECT_OK(result.status());
}
};
} // namespace internal
} // namespace fidl
namespace {
class ClientFixture : public zxtest::Test {
public:
ClientFixture() : loop_(&kAsyncLoopConfigNeverAttachToThread) {}
void SetUp() override {
zx::status endpoints = fidl::CreateEndpoints<TestProtocol>();
ASSERT_OK(endpoints.status_value());
endpoints_ = std::move(*endpoints);
}
async::Loop& loop() { return loop_; }
fidl::Endpoints<TestProtocol>& endpoints() { return endpoints_; }
fidl::IncomingMessage ReadFromServer() {
return fidl::ChannelReadEtc(endpoints_.server.channel().get(), 0,
fidl::BufferSpan(read_buffer_.data(), read_buffer_.size()),
cpp20::span<zx_handle_info_t>{});
}
private:
async::Loop loop_;
fidl::Endpoints<TestProtocol> endpoints_;
FIDL_ALIGNDECL std::array<uint8_t, ZX_CHANNEL_MAX_MSG_BYTES> read_buffer_;
};
class Client : public ClientFixture {};
class SharedClient : public ClientFixture {};
TEST_F(Client, DefaultConstruction) {
fidl::Client<TestProtocol> client;
EXPECT_FALSE(client.is_valid());
}
TEST_F(SharedClient, DefaultConstruction) {
fidl::SharedClient<TestProtocol> client;
EXPECT_FALSE(client.is_valid());
}
TEST_F(Client, Move) {
fidl::Client<TestProtocol> client;
client.Bind(std::move(endpoints().client), loop().dispatcher());
EXPECT_TRUE(client.is_valid());
fidl::Client<TestProtocol> client2 = std::move(client);
EXPECT_FALSE(client.is_valid());
EXPECT_TRUE(client2.is_valid());
ASSERT_DEATH([&] { client->SomeNaturalMethod(); });
}
TEST_F(SharedClient, Move) {
fidl::SharedClient<TestProtocol> client;
client.Bind(std::move(endpoints().client), loop().dispatcher());
EXPECT_TRUE(client.is_valid());
fidl::SharedClient<TestProtocol> client2 = std::move(client);
EXPECT_FALSE(client.is_valid());
EXPECT_TRUE(client2.is_valid());
ASSERT_DEATH([&] { client->SomeNaturalMethod(); });
}
TEST_F(SharedClient, Clone) {
fidl::SharedClient<TestProtocol> client;
client.Bind(std::move(endpoints().client), loop().dispatcher());
EXPECT_TRUE(client.is_valid());
fidl::SharedClient<TestProtocol> client2 = client.Clone();
EXPECT_TRUE(client.is_valid());
EXPECT_TRUE(client2.is_valid());
ASSERT_NO_DEATH([&] { client->SomeNaturalMethod(); });
ASSERT_NO_DEATH([&] { client2->SomeNaturalMethod(); });
}
TEST_F(Client, WireCall) {
fidl::Client client(std::move(endpoints().client), loop().dispatcher());
client.wire()->SomeWireMethod();
auto msg = ReadFromServer();
EXPECT_OK(msg.status());
}
TEST_F(SharedClient, WireCall) {
fidl::SharedClient client(std::move(endpoints().client), loop().dispatcher());
client.wire()->SomeWireMethod();
auto msg = ReadFromServer();
EXPECT_OK(msg.status());
}
TEST_F(Client, NaturalCall) {
fidl::Client client(std::move(endpoints().client), loop().dispatcher());
client->SomeNaturalMethod();
auto msg = ReadFromServer();
EXPECT_OK(msg.status());
}
TEST_F(SharedClient, NaturalCall) {
fidl::SharedClient client(std::move(endpoints().client), loop().dispatcher());
client->SomeNaturalMethod();
auto msg = ReadFromServer();
EXPECT_OK(msg.status());
}
} // namespace