blob: 5170641efc6661626e8bb95af170d7266e82a4c4 [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.
// This file contains manual test cases that should be migrated to GIDL
// and be generated as part of conformance_test.cc in the future.
#include <iostream>
#include <string>
#include <utility>
#include <vector>
#include <fidl/test/misc/llcpp/fidl.h>
#include <gtest/gtest.h>
#include "src/lib/fidl/llcpp/tests/test_utils.h"
namespace llcpp_misc = ::llcpp::fidl::test::misc;
TEST(InlineXUnionInStruct, Success) {
// clang-format off
const auto expected = std::vector<uint8_t>{
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "before"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "before" is present
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xunion header
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // envelope data present
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "after"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "after" is present
'b', 'e', 'f', 'o', 'r', 'e', // "before" string
0x00, 0x00, // 2 bytes of padding
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xunion header
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // envelope data present
0xef, 0xbe, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00, // envelope data
'a', 'f', 't', 'e', 'r', // "after" string
0x00, 0x00, 0x00, // 3 bytes of padding
};
// clang-format on
std::string before("before");
std::string after("after");
// encode
{
llcpp_misc::InlineXUnionInStruct input;
llcpp_misc::SimpleUnion simple_union;
int64_t i64 = 0xdeadbeef;
simple_union.set_i64(fidl::unowned_ptr(&i64));
input.before = fidl::unowned_str(before);
input.xu.set_su(fidl::unowned_ptr(&simple_union));
input.after = fidl::unowned_str(after);
fidl::OwnedEncodedMessage<llcpp_misc::InlineXUnionInStruct> encoded(&input);
ASSERT_STREQ(encoded.error(), nullptr);
ASSERT_TRUE(encoded.ok());
EXPECT_TRUE(llcpp_conformance_utils::ComparePayload(encoded.GetOutgoingMessage().bytes(),
encoded.GetOutgoingMessage().byte_actual(),
&expected[0], expected.size()));
}
// decode
{
std::vector<uint8_t> encoded_bytes = expected;
fidl::DecodedMessage<llcpp_misc::InlineXUnionInStruct> decoded(
encoded_bytes.data(), static_cast<uint32_t>(encoded_bytes.size()));
ASSERT_STREQ(decoded.error(), nullptr);
ASSERT_TRUE(decoded.ok());
const llcpp_misc::InlineXUnionInStruct& msg = *decoded.PrimaryObject();
ASSERT_STREQ(msg.before.begin(), &before[0]);
ASSERT_EQ(msg.before.size(), before.size());
ASSERT_STREQ(msg.after.begin(), &after[0]);
ASSERT_EQ(msg.after.size(), after.size());
ASSERT_EQ(msg.xu.which(), llcpp_misc::SampleXUnion::Tag::kSu);
const llcpp_misc::SimpleUnion& su = msg.xu.su();
ASSERT_EQ(su.which(), llcpp_misc::SimpleUnion::Tag::kI64);
ASSERT_EQ(su.i64(), 0xdeadbeef);
}
}
TEST(PrimitiveInXUnionInStruct, Success) {
// clang-format off
const auto expected = std::vector<uint8_t>{
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "before"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "before" is present
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xunion header
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // envelope data present
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "after"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "after" is present
'b', 'e', 'f', 'o', 'r', 'e', // "before" string
0x00, 0x00, // 2 bytes of padding
0xef, 0xbe, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00, // envelope content
'a', 'f', 't', 'e', 'r', // "after" string
0x00, 0x00, 0x00, // 3 bytes of padding
};
// clang-format on
std::string before("before");
std::string after("after");
int32_t integer = 0xdeadbeef;
// encode
{
llcpp_misc::InlineXUnionInStruct input;
input.before = fidl::unowned_str(before);
input.xu.set_i(fidl::unowned_ptr(&integer));
input.after = fidl::unowned_str(after);
fidl::OwnedEncodedMessage<llcpp_misc::InlineXUnionInStruct> encoded(&input);
ASSERT_STREQ(encoded.error(), nullptr);
ASSERT_TRUE(encoded.ok());
EXPECT_TRUE(llcpp_conformance_utils::ComparePayload(encoded.GetOutgoingMessage().bytes(),
encoded.GetOutgoingMessage().byte_actual(),
&expected[0], expected.size()));
}
// decode
{
std::vector<uint8_t> encoded_bytes = expected;
fidl::DecodedMessage<llcpp_misc::InlineXUnionInStruct> decoded(
encoded_bytes.data(), static_cast<uint32_t>(encoded_bytes.size()), nullptr, 0);
ASSERT_STREQ(decoded.error(), nullptr);
ASSERT_TRUE(decoded.ok());
const llcpp_misc::InlineXUnionInStruct& msg = *decoded.PrimaryObject();
ASSERT_STREQ(msg.before.begin(), &before[0]);
ASSERT_EQ(msg.before.size(), before.size());
ASSERT_STREQ(msg.after.begin(), &after[0]);
ASSERT_EQ(msg.after.size(), after.size());
ASSERT_EQ(msg.xu.which(), llcpp_misc::SampleXUnion::Tag::kI);
const int32_t& i = msg.xu.i();
ASSERT_EQ(i, integer);
}
}
TEST(InlineXUnionInStruct, FailToEncodeAbsentXUnion) {
llcpp_misc::InlineXUnionInStruct input = {};
std::string empty_str = "";
input.before = fidl::unowned_str(empty_str);
input.after = fidl::unowned_str(empty_str);
fidl::OwnedEncodedMessage<llcpp_misc::InlineXUnionInStruct> encoded(&input);
EXPECT_STREQ(encoded.error(), "non-nullable xunion is absent");
EXPECT_EQ(encoded.status(), ZX_ERR_INVALID_ARGS);
}
TEST(InlineXUnionInStruct, FailToDecodeAbsentXUnion) {
// clang-format off
std::vector<uint8_t> encoded_bytes = std::vector<uint8_t>{
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "before"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "before" is present
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // null xunion header
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // num bytes; num handles
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // envelope data absent
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "after"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "after" is present
'b', 'e', 'f', 'o', 'r', 'e', // "before" string
0x00, 0x00, // 2 bytes of padding
'a', 'f', 't', 'e', 'r', // "after" string
0x00, 0x00, 0x00, // 3 bytes of padding
};
// clang-format on
fidl::DecodedMessage<llcpp_misc::InlineXUnionInStruct> decoded(
encoded_bytes.data(), static_cast<uint32_t>(encoded_bytes.size()), nullptr, 0);
EXPECT_STREQ(decoded.error(), "non-nullable xunion is absent");
EXPECT_EQ(decoded.status(), ZX_ERR_INVALID_ARGS);
}
TEST(InlineXUnionInStruct, FailToDecodeZeroOrdinalXUnion) {
// clang-format off
std::vector<uint8_t> encoded_bytes = std::vector<uint8_t>{
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "before"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "before" is present
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // null xunion header
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // envelope data present
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "after"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "after" is present
'b', 'e', 'f', 'o', 'r', 'e', // "before" string
0x00, 0x00, // 2 bytes of padding
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // envelope content
'a', 'f', 't', 'e', 'r', // "after" string
0x00, 0x00, 0x00, // 3 bytes of padding
};
// clang-format on
fidl::DecodedMessage<llcpp_misc::InlineXUnionInStruct> decoded(
encoded_bytes.data(), static_cast<uint32_t>(encoded_bytes.size()), nullptr, 0);
EXPECT_STREQ(decoded.error(), "xunion with zero as ordinal must be empty");
EXPECT_EQ(decoded.status(), ZX_ERR_INVALID_ARGS);
}
// The xunion ordinal hashing algorithm generates 32 bit values. But if it did
// generate values bigger than that, they would decode successfully
TEST(InlineXUnionInStruct, SuccessLargeXUnionOrdinal) {
// clang-format off
auto encoded_bytes = std::vector<uint8_t>{
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "before"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "before" is present
0x53, 0x76, 0x31, 0x6f, 0xaa, 0xaa, 0xaa, 0xaa, // xunion header
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // envelope data present
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "after"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "after" is present
'b', 'e', 'f', 'o', 'r', 'e', // "before" string
0x00, 0x00, // 2 bytes of padding
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // envelope content
0xef, 0xbe, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
'a', 'f', 't', 'e', 'r', // "after" string
0x00, 0x00, 0x00, // 3 bytes of padding
};
// clang-format on
fidl::DecodedMessage<llcpp_misc::InlineXUnionInStruct> decoded(
encoded_bytes.data(), static_cast<uint32_t>(encoded_bytes.size()), nullptr, 0);
ASSERT_TRUE(decoded.ok());
}
TEST(ComplexTable, SuccessEmpty) {
// clang-format off
const auto expected = std::vector<uint8_t>{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // number of envelopes in ComplexTable
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // envelopes data pointer is present
};
// clang-format on
// encode
{
llcpp_misc::ComplexTable::UnownedBuilder builder;
auto input = builder.build();
fidl::OwnedEncodedMessage<llcpp_misc::ComplexTable> encoded(&input);
ASSERT_STREQ(encoded.error(), nullptr);
ASSERT_TRUE(encoded.ok());
EXPECT_TRUE(llcpp_conformance_utils::ComparePayload(encoded.GetOutgoingMessage().bytes(),
encoded.GetOutgoingMessage().byte_actual(),
&expected[0], expected.size()));
}
// decode
{
std::vector<uint8_t> encoded_bytes = expected;
fidl::DecodedMessage<llcpp_misc::ComplexTable> decoded(
encoded_bytes.data(), static_cast<uint32_t>(encoded_bytes.size()), nullptr, 0);
ASSERT_STREQ(decoded.error(), nullptr);
ASSERT_TRUE(decoded.ok());
const llcpp_misc::ComplexTable& msg = *decoded.PrimaryObject();
ASSERT_FALSE(msg.has_simple());
ASSERT_FALSE(msg.has_u());
ASSERT_FALSE(msg.has_strings());
}
}
TEST(ComplexTable, FailToDecodeAbsentTable) {
// clang-format off
auto encoded_bytes = std::vector<uint8_t>{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // number of envelopes in ComplexTable
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // envelopes data pointer is absent
};
// clang-format on
fidl::DecodedMessage<llcpp_misc::ComplexTable> decoded(
encoded_bytes.data(), static_cast<uint32_t>(encoded_bytes.size()), nullptr, 0);
ASSERT_STREQ(decoded.error(), "absent pointer disallowed in non-nullable collection");
ASSERT_EQ(decoded.status(), ZX_ERR_INVALID_ARGS);
}
TEST(ComplexTable, Success) {
// clang-format off
const auto expected = std::vector<uint8_t>{
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // number of envelopes in ComplexTable
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // envelopes data pointer is present
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #1: num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // #1: envelope data present
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #2: num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // #2: envelope data present
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #3: num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // #3: envelope data present
// SimpleTable
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // number of envelopes in SimpleTable
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // envelopes data pointer is present
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #1: num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // #1: envelope data present
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #2: num bytes; num handles
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #2: envelope data absent
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #3: num bytes; num handles
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #3: envelope data absent
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #4: num bytes; num handles
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #4: envelope data absent
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #5: num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // #5: envelope data present
0x0d, 0xf0, 0xad, 0x8b, 0xcd, 0xab, 0xcd, 0xab, // SimpleTable.x: 0xabcdabcd8badf00d
0xd1, 0xf1, 0xd1, 0xf1, 0x78, 0x56, 0x34, 0x12, // SimpleTable.y: 0x12345678f1d1f1d1
// SampleXUnion
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xunion header
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // num bytes; num handles
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // envelope data present
0xef, 0xbe, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00, // SampleXUnion.i: 0xdeadbeef
// vector<string>
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of string vector
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // string vector data present
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "before"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "before" is present
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // length of "after"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // "after" is present
'b', 'e', 'f', 'o', 'r', 'e', // "before" string
0x00, 0x00, // 2 bytes of padding
'a', 'f', 't', 'e', 'r', // "after" string
0x00, 0x00, 0x00, // 3 bytes of padding
};
// clang-format on
std::string before("before");
std::string after("after");
int64_t table_x = 0xabcdabcd8badf00d;
int64_t table_y = 0x12345678f1d1f1d1;
int32_t xunion_i = 0xdeadbeef;
// encode
{
auto simple_builder = llcpp_misc::SimpleTable::UnownedBuilder()
.set_x(fidl::unowned_ptr(&table_x))
.set_y(fidl::unowned_ptr(&table_y));
auto simple_table = simple_builder.build();
llcpp_misc::SampleXUnion xu;
xu.set_i(fidl::unowned_ptr(&xunion_i));
fidl::StringView strings_vector[]{
fidl::unowned_str(before),
fidl::unowned_str(after),
};
fidl::VectorView<fidl::StringView> strings = fidl::unowned_vec(strings_vector);
auto builder = llcpp_misc::ComplexTable::UnownedBuilder()
.set_simple(fidl::unowned_ptr(&simple_table))
.set_u(fidl::unowned_ptr(&xu))
.set_strings(fidl::unowned_ptr(&strings));
auto input = builder.build();
fidl::OwnedEncodedMessage<llcpp_misc::ComplexTable> encoded(&input);
ASSERT_STREQ(encoded.error(), nullptr);
ASSERT_TRUE(encoded.ok());
EXPECT_TRUE(llcpp_conformance_utils::ComparePayload(encoded.GetOutgoingMessage().bytes(),
encoded.GetOutgoingMessage().byte_actual(),
&expected[0], expected.size()));
}
// decode
{
std::vector<uint8_t> encoded_bytes = expected;
fidl::DecodedMessage<llcpp_misc::ComplexTable> decoded(
encoded_bytes.data(), static_cast<uint32_t>(encoded_bytes.size()), nullptr, 0);
ASSERT_STREQ(decoded.error(), nullptr);
ASSERT_TRUE(decoded.ok());
const llcpp_misc::ComplexTable& msg = *decoded.PrimaryObject();
ASSERT_TRUE(msg.has_simple());
ASSERT_TRUE(msg.simple().has_x());
ASSERT_EQ(msg.simple().x(), table_x);
ASSERT_TRUE(msg.simple().has_y());
ASSERT_EQ(msg.simple().y(), table_y);
ASSERT_TRUE(msg.has_u());
ASSERT_EQ(msg.u().which(), llcpp_misc::SampleXUnion::Tag::kI);
const int32_t& i = msg.u().i();
ASSERT_EQ(i, xunion_i);
ASSERT_TRUE(msg.has_strings());
ASSERT_EQ(msg.strings().count(), 2u);
ASSERT_STREQ(msg.strings()[0].begin(), &before[0]);
ASSERT_EQ(msg.strings()[0].size(), before.size());
ASSERT_STREQ(msg.strings()[1].begin(), &after[0]);
ASSERT_EQ(msg.strings()[1].size(), after.size());
}
}