blob: 6a25eed6ca2fe8ee92ec739f293d0d619dbb0f3a [file]
// Copyright 2022 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.
#ifndef LIB_FIDL_CPP_TESTS_CONFORMANCE_CONFORMANCE_UTILS_H_
#define LIB_FIDL_CPP_TESTS_CONFORMANCE_CONFORMANCE_UTILS_H_
#include <lib/fidl/cpp/features.h>
#include <lib/fidl/cpp/natural_types.h>
#include <lib/fidl/internal.h>
#if __FIDL_SUPPORT_HANDLES
#include <lib/fidl/cpp/wire/internal/transport_channel.h>
#include <lib/zx/channel.h>
#else
#include <lib/fidl/cpp/wire/internal/transport_channel_host.h>
#endif // __FIDL_SUPPORT_HANDLES
#include <zxtest/zxtest.h>
namespace conformance_utils {
#if __FIDL_SUPPORT_HANDLES
inline zx_handle_t HandleReplace(zx_handle_t handle, zx_rights_t rights) {
zx_handle_t replaced_handle;
ZX_ASSERT(zx_handle_replace(handle, rights, &replaced_handle) == ZX_OK);
return replaced_handle;
}
inline zx_handle_t CreateChannel(zx_rights_t rights) {
zx_handle_t c1, c2;
ZX_ASSERT(zx_channel_create(0, &c1, &c2) == ZX_OK);
zx_handle_close(c1);
return HandleReplace(c2, rights);
}
inline zx_handle_t CreateEvent(zx_rights_t rights) {
zx_handle_t e;
ZX_ASSERT(zx_event_create(0, &e) == ZX_OK);
return HandleReplace(e, rights);
}
#endif // __FIDL_SUPPORT_HANDLES
inline fidl::WireFormatMetadata CreateWireFormatMetadata(
fidl::internal::WireFormatVersion wire_format_version) {
ZX_DEBUG_ASSERT(wire_format_version == fidl::internal::WireFormatVersion::kV2);
return fidl::internal::WireFormatMetadataForVersion(wire_format_version);
}
template <typename FidlType>
void EncodeSuccess(fidl::internal::WireFormatVersion wire_format_version, FidlType& obj,
const std::vector<uint8_t>& expected_bytes,
const std::vector<zx_handle_disposition_t> expected_handles,
bool check_handle_rights) {
fidl::OwnedEncodeResult result = fidl::StandaloneEncode(std::move(obj));
ASSERT_TRUE(result.message().ok(), "Error encoding: %s",
result.message().error().FormatDescription().c_str());
auto result_bytes = result.message().CopyBytes();
ASSERT_EQ(expected_bytes.size(), result_bytes.size());
ASSERT_BYTES_EQ(expected_bytes.data(), result_bytes.data(), expected_bytes.size());
ASSERT_EQ(expected_handles.size(), result.message().handle_actual());
for (uint32_t i = 0; i < expected_handles.size(); i++) {
ASSERT_EQ(expected_handles[i].handle, result.message().handles()[i]);
if (check_handle_rights) {
ASSERT_EQ(expected_handles[i].type,
result.message().handle_metadata<fidl::internal::ChannelTransport>()[i].obj_type);
ASSERT_EQ(expected_handles[i].rights,
result.message().handle_metadata<fidl::internal::ChannelTransport>()[i].rights);
}
}
}
template <typename FidlType, typename EqualityCheck>
void DecodeSuccess(fidl::internal::WireFormatVersion wire_format_version,
std::vector<uint8_t>& bytes, const std::vector<zx_handle_info_t> handle_infos,
EqualityCheck equality_check) {
auto handles = std::make_unique<zx_handle_t[]>(handle_infos.size());
auto handle_metadata = std::make_unique<fidl_channel_handle_metadata_t[]>(handle_infos.size());
for (uint32_t i = 0; i < handle_infos.size(); i++) {
handles[i] = handle_infos[i].handle;
handle_metadata[i] = {
.obj_type = handle_infos[i].type,
.rights = handle_infos[i].rights,
};
}
auto message = fidl::EncodedMessage::Create<fidl::internal::ChannelTransport>(
cpp20::span(bytes), handles.get(), handle_metadata.get(),
static_cast<uint32_t>(handle_infos.size()));
auto result = fidl::StandaloneDecode<FidlType>(std::move(message),
CreateWireFormatMetadata(wire_format_version));
ASSERT_TRUE(result.is_ok(), "Error decoding: %s",
result.error_value().FormatDescription().c_str());
equality_check(result.value());
}
template <typename FidlType>
void EncodeFailure(fidl::internal::WireFormatVersion wire_format_version, FidlType& obj) {
fidl::OwnedEncodeResult result = fidl::StandaloneEncode(std::move(obj));
ASSERT_FALSE(result.message().ok());
}
template <typename FidlType>
void DecodeFailure(fidl::internal::WireFormatVersion wire_format_version,
std::vector<uint8_t>& bytes, const std::vector<zx_handle_info_t> handle_infos) {
auto handles = std::make_unique<zx_handle_t[]>(handle_infos.size());
auto handle_metadata = std::make_unique<fidl_channel_handle_metadata_t[]>(handle_infos.size());
for (uint32_t i = 0; i < handle_infos.size(); i++) {
handles[i] = handle_infos[i].handle;
handle_metadata[i] = {
.obj_type = handle_infos[i].type,
.rights = handle_infos[i].rights,
};
}
auto message = fidl::EncodedMessage::Create<fidl::internal::ChannelTransport>(
cpp20::span(bytes), handles.get(), handle_metadata.get(),
static_cast<uint32_t>(handle_infos.size()));
auto result = fidl::StandaloneDecode<FidlType>(std::move(message),
CreateWireFormatMetadata(wire_format_version));
ASSERT_TRUE(result.is_error());
}
} // namespace conformance_utils
#endif // LIB_FIDL_CPP_TESTS_CONFORMANCE_CONFORMANCE_UTILS_H_