blob: 8e6e5014598b5bc9e3f544156cff52e76ec4fbc7 [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/fidl.llcpp.empty.test/cpp/wire_messaging.h>
#include <fidl/fidl.llcpp.linearized.test/cpp/wire_types.h>
#include <fidl/fidl.test.misc/cpp/wire_messaging.h>
#include <lib/fidl/cpp/wire/message.h>
#include <lib/fidl/cpp/wire/wire_messaging_declarations.h>
#include <zircon/errors.h>
#include <iterator>
#include <gtest/gtest.h>
TEST(OutgoingMessage, Create) {
zx_channel_iovec_t iovecs[1];
zx_handle_t handles[2];
fidl_channel_handle_metadata_t handle_metadata[2];
uint8_t backing_buffer[1];
fidl::OutgoingMessage msg = fidl::OutgoingMessage::Create_InternalMayBreak({
.transport_vtable = &fidl::internal::ChannelTransport::VTable,
.iovecs = iovecs,
.iovec_capacity = std::size(iovecs),
.handles = handles,
.handle_metadata = reinterpret_cast<fidl_handle_metadata_t*>(handle_metadata),
.handle_capacity = std::size(handles),
.backing_buffer = backing_buffer,
.backing_buffer_capacity = std::size(backing_buffer),
});
// Capacities are stored but not exposed. Actual sizes are zero initialized.
EXPECT_EQ(0u, msg.iovec_actual());
EXPECT_EQ(iovecs, msg.iovecs());
EXPECT_EQ(0u, msg.handle_actual());
EXPECT_EQ(handles, msg.handles());
EXPECT_EQ(fidl::internal::fidl_transport_type::kChannel, msg.transport_type());
EXPECT_EQ(handle_metadata, msg.handle_metadata<fidl::internal::ChannelTransport>());
}
TEST(OutgoingMessage, OutgoingMessageBytesMatch) {
uint8_t bytes_a1[]{1};
uint8_t bytes_a2[]{2, 3, 4};
zx_channel_iovec_t iovecs_a[] = {
{
.buffer = bytes_a1,
.capacity = std::size(bytes_a1),
.reserved = 0,
},
{
.buffer = bytes_a2,
.capacity = std::size(bytes_a2),
.reserved = 0,
},
};
auto msg_a = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs_a,
.num_iovecs = std::size(iovecs_a),
});
uint8_t bytes_b1[]{1, 2};
uint8_t bytes_b2[]{3};
uint8_t bytes_b3[]{4};
zx_channel_iovec_t iovecs_b[] = {
{
.buffer = bytes_b1,
.capacity = std::size(bytes_b1),
.reserved = 0,
},
{
.buffer = bytes_b2,
.capacity = std::size(bytes_b2),
.reserved = 0,
},
{
.buffer = bytes_b3,
.capacity = std::size(bytes_b3),
.reserved = 0,
},
};
auto msg_b = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs_b,
.num_iovecs = std::size(iovecs_b),
});
EXPECT_TRUE(msg_a.BytesMatch(msg_b));
EXPECT_TRUE(msg_b.BytesMatch(msg_a));
}
TEST(OutgoingMessage, OutgoingMessageBytesMatchIgnoreHandles) {
uint8_t bytes[]{1, 2, 3, 4};
zx_channel_iovec_t iovecs[] = {
{
.buffer = bytes,
.capacity = std::size(bytes),
.reserved = 0,
},
};
auto msg_without_handles = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs,
.num_iovecs = std::size(iovecs),
});
// Bytes should match even if one has handles and the other doesn't.
zx_handle_t handle;
fidl_channel_handle_metadata_t handle_metadata;
ASSERT_EQ(ZX_OK, zx_event_create(0, &handle));
auto msg_with_handles = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs,
.num_iovecs = std::size(iovecs),
.handles = &handle,
.handle_metadata = reinterpret_cast<fidl_handle_metadata_t*>(&handle_metadata),
.num_handles = 1,
});
EXPECT_TRUE(msg_without_handles.BytesMatch(msg_with_handles));
EXPECT_TRUE(msg_with_handles.BytesMatch(msg_without_handles));
}
TEST(OutgoingMessage, OutgoingMessageBytesMismatchByteLength) {
uint8_t bytes[]{1, 2, 3};
// 2 bytes.
zx_channel_iovec_t iovecs_a[] = {
{
.buffer = bytes,
.capacity = 2,
.reserved = 0,
},
};
auto msg_a = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs_a,
.num_iovecs = std::size(iovecs_a),
});
// 3 bytes.
zx_channel_iovec_t iovecs_b[] = {
{
.buffer = bytes,
.capacity = 3,
.reserved = 0,
},
};
auto msg_b = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs_b,
.num_iovecs = std::size(iovecs_b),
});
EXPECT_FALSE(msg_a.BytesMatch(msg_b));
EXPECT_FALSE(msg_b.BytesMatch(msg_a));
}
TEST(OutgoingMessage, OutgoingMessageBytesMismatchIovecLength) {
uint8_t bytes1[]{1, 2};
uint8_t bytes2[]{3};
// 1 iovec.
zx_channel_iovec_t iovecs_a[] = {
{
.buffer = bytes1,
.capacity = sizeof(bytes1),
.reserved = 0,
},
};
auto msg_a = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs_a,
.num_iovecs = std::size(iovecs_a),
});
// 2 iovecs.
zx_channel_iovec_t iovecs_b[] = {
{
.buffer = bytes1,
.capacity = std::size(bytes1),
.reserved = 0,
},
{
.buffer = bytes2,
.capacity = std::size(bytes2),
.reserved = 0,
},
};
auto msg_b = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs_b,
.num_iovecs = std::size(iovecs_b),
});
EXPECT_FALSE(msg_a.BytesMatch(msg_b));
EXPECT_FALSE(msg_b.BytesMatch(msg_a));
}
TEST(OutgoingMessage, OutgoingMessageBytesMismatch) {
uint8_t bytes_a1[]{1};
uint8_t bytes_a2[]{2, 3, 4};
zx_channel_iovec_t iovecs_a[] = {
{
.buffer = bytes_a1,
.capacity = std::size(bytes_a1),
.reserved = 0,
},
{
.buffer = bytes_a2,
.capacity = std::size(bytes_a2),
.reserved = 0,
},
};
auto msg_a = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs_a,
.num_iovecs = std::size(iovecs_a),
});
uint8_t bytes_b1[]{1, 2};
uint8_t bytes_b2[]{5};
uint8_t bytes_b3[]{4};
zx_channel_iovec_t iovecs_b[] = {
{
.buffer = bytes_b1,
.capacity = std::size(bytes_b1),
.reserved = 0,
},
{
.buffer = bytes_b2,
.capacity = std::size(bytes_b2),
.reserved = 0,
},
{
.buffer = bytes_b3,
.capacity = std::size(bytes_b3),
.reserved = 0,
},
};
auto msg_b = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs_b,
.num_iovecs = std::size(iovecs_b),
});
EXPECT_FALSE(msg_a.BytesMatch(msg_b));
EXPECT_FALSE(msg_b.BytesMatch(msg_a));
}
TEST(OutgoingMessage, OutgoingMessageCopiedBytes) {
uint8_t bytes1[]{1, 2};
uint8_t bytes2[]{3};
uint8_t bytes3[]{4};
zx_channel_iovec_t iovecs[] = {
{
.buffer = bytes1,
.capacity = std::size(bytes1),
.reserved = 0,
},
{
.buffer = bytes2,
.capacity = std::size(bytes2),
.reserved = 0,
},
{
.buffer = bytes3,
.capacity = std::size(bytes3),
.reserved = 0,
},
};
auto msg = fidl::OutgoingMessage::Create_InternalMayBreak({
.iovecs = iovecs,
.num_iovecs = std::size(iovecs),
});
uint8_t expected_bytes[] = {1, 2, 3, 4};
EXPECT_EQ(4u, msg.CountBytes());
fidl::OutgoingMessage::CopiedBytes msg_bytes = msg.CopyBytes();
EXPECT_EQ(std::size(expected_bytes), msg_bytes.size());
EXPECT_EQ(0, memcmp(expected_bytes, msg_bytes.data(), std::size(expected_bytes)));
}
TEST(OutgoingMessage, SettingTxIdRequiresTransactionalMessageNegative) {
fidl_llcpp_linearized_test::wire::NoOpLinearizedStruct value{.x = 42};
fidl::internal::OwnedEncodedMessage<fidl_llcpp_linearized_test::wire::NoOpLinearizedStruct>
encoded(fidl::internal::WireFormatVersion::kV2, &value);
ASSERT_EQ(ZX_OK, encoded.status());
ASSERT_DEATH({ encoded.GetOutgoingMessage().set_txid(1); }, "transactional");
}
TEST(OutgoingMessage, SettingTxIdRequiresTransactionalMessagePositive) {
using Request = fidl::internal::TransactionalRequest<fidl_test_misc::Echo::EchoString>;
Request request{fidl::StringView("")};
fidl::internal::OwnedEncodedMessage<Request> encoded(fidl::internal::WireFormatVersion::kV2,
&request);
ASSERT_EQ(ZX_OK, encoded.status());
encoded.GetOutgoingMessage().set_txid(1);
}