blob: fe1cae905611df21b9e91aa1bfbbf3b5fe786622 [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 <fidl/llcpptest.v2integration.test/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fidl/cpp/wire/message.h>
#include <iterator>
#include <thread>
#include <gtest/gtest.h>
typedef struct {
uint64_t ordinal;
uint32_t value;
uint16_t num_handles;
uint16_t flags;
} union_t;
using TestProtocol = ::llcpptest_v2integration_test::TestProtocol;
void SingleResponseServer(zx::channel ch) {
ZX_ASSERT(ZX_OK == ch.wait_one(ZX_CHANNEL_READABLE, zx::time::infinite(), nullptr));
std::unique_ptr<uint8_t[]> bytes_in = std::make_unique<uint8_t[]>(ZX_CHANNEL_MAX_MSG_BYTES);
ZX_ASSERT(ZX_OK ==
ch.read_etc(0, bytes_in.get(), nullptr, ZX_CHANNEL_MAX_MSG_BYTES, 0, nullptr, nullptr));
fidl_message_header_t header_in;
memcpy(&header_in, bytes_in.get(), sizeof(header_in));
fidl_message_header_t header_out = {
.txid = header_in.txid,
.at_rest_flags = {FIDL_MESSAGE_HEADER_AT_REST_FLAGS_0_USE_VERSION_V2, 0},
.dynamic_flags = 0,
.magic_number = header_in.magic_number,
.ordinal = header_in.ordinal,
};
union_t payload_out = {
.ordinal = 1,
.value = 123,
.num_handles = 0,
.flags = 1, // 1 == inlined
};
uint8_t bytes_out[sizeof(header_out) + sizeof(payload_out)] = {};
memcpy(bytes_out, &header_out, sizeof(header_out));
memcpy(bytes_out + sizeof(header_out), &payload_out, sizeof(payload_out));
ZX_ASSERT(ZX_OK == ch.write_etc(0, bytes_out, std::size(bytes_out), nullptr, 0));
}
// Tests an LLCPP sync client where the server returns a V2 message.
TEST(V2Integration, SyncCallResponseDecode) {
zx::channel ch1, ch2;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &ch1, &ch2));
std::thread server_thread([&ch2]() { SingleResponseServer(std::move(ch2)); });
fidl::ClientEnd<TestProtocol> client_end(std::move(ch1));
fidl::WireSyncClient<TestProtocol> client(std::move(client_end));
auto result = client->MethodWithResponse();
ASSERT_TRUE(result.ok());
ASSERT_EQ(123u, result.value().u.v());
server_thread.join();
}
// Tests an LLCPP async client where the server returns a V2 message.
TEST(V2Integration, AsyncCallResponseDecode) {
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
ASSERT_EQ(ZX_OK, loop.StartThread());
zx::channel ch1, ch2;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &ch1, &ch2));
std::thread server_thread([&ch2]() { SingleResponseServer(std::move(ch2)); });
fidl::ClientEnd<TestProtocol> client_end(std::move(ch1));
fidl::WireSharedClient<TestProtocol> client(std::move(client_end), loop.dispatcher());
sync_completion_t done;
client->MethodWithResponse().ThenExactlyOnce(
[&done](fidl::WireUnownedResult<TestProtocol::MethodWithResponse>& result) {
ASSERT_EQ(ZX_OK, result.status());
ASSERT_EQ(123u, result.value().u.v());
sync_completion_signal(&done);
});
ASSERT_EQ(ZX_OK, sync_completion_wait(&done, ZX_TIME_INFINITE));
server_thread.join();
}
// Tests an LLCPP server which decodes a V2 request.
TEST(V2Integration, ServerRequestDecode) {
class Server : public fidl::WireServer<TestProtocol> {
public:
Server(sync_completion_t* done) : done_(done) {}
void MethodWithRequest(MethodWithRequestRequestView request,
MethodWithRequestCompleter::Sync& completer) override {
ASSERT_EQ(123u, request->u.v());
sync_completion_signal(done_);
}
void MethodWithResponse(MethodWithResponseCompleter::Sync& completer) override {
ZX_PANIC("Not used in this test");
}
private:
sync_completion_t* done_;
};
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
ASSERT_EQ(ZX_OK, loop.StartThread());
zx::channel ch1, ch2;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &ch1, &ch2));
sync_completion_t done;
fidl::ServerEnd<TestProtocol> server_end(std::move(ch2));
fidl::BindServer(loop.dispatcher(), std::move(server_end), std::make_unique<Server>(&done));
fidl_message_header_t header = {
.txid = 100,
.at_rest_flags = {FIDL_MESSAGE_HEADER_AT_REST_FLAGS_0_USE_VERSION_V2, 0},
.dynamic_flags = 0,
.magic_number = kFidlWireFormatMagicNumberInitial,
.ordinal = 8068486508660569159ull,
};
union_t payload = {
.ordinal = 1,
.value = 123,
.num_handles = 0,
.flags = 1, // 1 == inlined
};
uint8_t bytes[sizeof(header) + sizeof(payload)] = {};
memcpy(bytes, &header, sizeof(header));
memcpy(bytes + sizeof(header), &payload, sizeof(payload));
ASSERT_EQ(ZX_OK, ch1.write_etc(0, bytes, std::size(bytes), nullptr, 0));
ASSERT_EQ(ZX_OK, sync_completion_wait(&done, ZX_TIME_INFINITE));
}