blob: e43a884aa0fc2491f4a79441a6cf4ee631fccf87 [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.
#include <iostream>
#include <string>
#include <utility>
#include <vector>
#include <fidl/test/misc/llcpp/fidl.h>
#include "gtest/gtest.h"
bool ComparePayload(const uint8_t* actual, size_t actual_size,
const uint8_t* expected, size_t expected_size) {
bool pass = true;
for (size_t i = 0; i < actual_size && i < expected_size; i++) {
if (actual[i] != expected[i]) {
pass = false;
std::cout << std::dec << "element[" << i << "]: " << std::hex
<< "actual=0x" << +actual[i] << " "
<< "expected=0x" << +expected[i] << "\n";
}
}
if (actual_size != expected_size) {
pass = false;
std::cout << std::dec << "element[...]: "
<< "actual.size=" << +actual_size << " "
<< "expected.size=" << +expected_size << "\n";
}
return pass;
}
TEST(InlineXUnionInStruct, Success) {
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
0x53, 0x76, 0x31, 0x6f, 0x00, 0x00, 0x00, 0x00, // 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
};
std::string before("before");
std::string after("after");
// encode
{
fidl::test::misc::InlineXUnionInStruct input;
fidl::test::misc::SimpleUnion simple_union;
simple_union.set_i64(0xdeadbeef);
input.before = fidl::StringView(before.size(), &before[0]);
input.xu.set_su(&simple_union);
input.after = fidl::StringView(after.size(), &after[0]);
std::vector<uint8_t> buffer(ZX_CHANNEL_MAX_MSG_BYTES);
fidl::BytePart bytes(&buffer[0], static_cast<uint32_t>(buffer.size()));
auto linearize_result = fidl::Linearize(&input, std::move(bytes));
ASSERT_STREQ(linearize_result.error, nullptr);
ASSERT_EQ(linearize_result.status, ZX_OK);
auto encode_result = fidl::Encode(std::move(linearize_result.message));
ASSERT_STREQ(encode_result.error, nullptr);
ASSERT_EQ(encode_result.status, ZX_OK);
EXPECT_TRUE(ComparePayload(encode_result.message.bytes().begin(),
encode_result.message.bytes().size(),
&expected[0], expected.size()));
}
// decode
{
std::vector<uint8_t> encoded_bytes = expected;
fidl::EncodedMessage<fidl::test::misc::InlineXUnionInStruct> encoded_msg(
fidl::BytePart(&encoded_bytes[0],
static_cast<uint32_t>(encoded_bytes.size()),
static_cast<uint32_t>(encoded_bytes.size())));
auto decode_result = fidl::Decode(std::move(encoded_msg));
ASSERT_STREQ(decode_result.error, nullptr);
ASSERT_EQ(decode_result.status, ZX_OK);
const fidl::test::misc::InlineXUnionInStruct& msg =
*decode_result.message.message();
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(), fidl::test::misc::SampleXUnion::Tag::kSu);
const fidl::test::misc::SimpleUnion& su = msg.xu.su();
ASSERT_EQ(su.which(), fidl::test::misc::SimpleUnion::Tag::kI64);
ASSERT_EQ(su.i64(), 0xdeadbeef);
}
}
TEST(PrimitiveInXUnionInStruct, Success) {
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
0xa5, 0x47, 0xdf, 0x29, 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
};
std::string before("before");
std::string after("after");
int32_t integer = 0xdeadbeef;
// encode
{
fidl::test::misc::InlineXUnionInStruct input;
input.before = fidl::StringView(before.size(), &before[0]);
input.xu.set_i(&integer);
input.after = fidl::StringView(after.size(), &after[0]);
std::vector<uint8_t> buffer(ZX_CHANNEL_MAX_MSG_BYTES);
fidl::BytePart bytes(&buffer[0], static_cast<uint32_t>(buffer.size()));
auto linearize_result = fidl::Linearize(&input, std::move(bytes));
ASSERT_STREQ(linearize_result.error, nullptr);
ASSERT_EQ(linearize_result.status, ZX_OK);
auto encode_result = fidl::Encode(std::move(linearize_result.message));
ASSERT_STREQ(encode_result.error, nullptr);
ASSERT_EQ(encode_result.status, ZX_OK);
EXPECT_TRUE(ComparePayload(encode_result.message.bytes().begin(),
encode_result.message.bytes().size(),
&expected[0], expected.size()));
}
// decode
{
std::vector<uint8_t> encoded_bytes = expected;
fidl::EncodedMessage<fidl::test::misc::InlineXUnionInStruct> encoded_msg(
fidl::BytePart(&encoded_bytes[0],
static_cast<uint32_t>(encoded_bytes.size()),
static_cast<uint32_t>(encoded_bytes.size())));
auto decode_result = fidl::Decode(std::move(encoded_msg));
ASSERT_STREQ(decode_result.error, nullptr);
ASSERT_EQ(decode_result.status, ZX_OK);
const fidl::test::misc::InlineXUnionInStruct& msg =
*decode_result.message.message();
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(), fidl::test::misc::SampleXUnion::Tag::kI);
const int32_t& i = msg.xu.i();
ASSERT_EQ(i, integer);
}
}
TEST(InlineXUnionInStruct, FailToEncodeAbsentXUnion) {
fidl::test::misc::InlineXUnionInStruct input = {};
std::string empty_str = "";
input.before = fidl::StringView(empty_str.size(), &empty_str[0]);
input.after = fidl::StringView(empty_str.size(), &empty_str[0]);
std::vector<uint8_t> buffer(ZX_CHANNEL_MAX_MSG_BYTES);
fidl::BytePart bytes(&buffer[0], static_cast<uint32_t>(buffer.size()));
auto linearize_result = fidl::Linearize(&input, std::move(bytes));
EXPECT_STREQ(linearize_result.error,
"non-nullable xunion is absent");
EXPECT_EQ(linearize_result.status, ZX_ERR_INVALID_ARGS);
}
TEST(InlineXUnionInStruct, FailToDecodeAbsentXUnion) {
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
};
fidl::EncodedMessage<fidl::test::misc::InlineXUnionInStruct> encoded_msg(
fidl::BytePart(&encoded_bytes[0],
static_cast<uint32_t>(encoded_bytes.size()),
static_cast<uint32_t>(encoded_bytes.size())));
auto decode_result = fidl::Decode(std::move(encoded_msg));
EXPECT_STREQ(decode_result.error,
"non-nullable xunion is absent");
EXPECT_EQ(decode_result.status, ZX_ERR_INVALID_ARGS);
}
TEST(InlineXUnionInStruct, FailToDecodeZeroOrdinalXUnion) {
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
};
fidl::EncodedMessage<fidl::test::misc::InlineXUnionInStruct> encoded_msg(
fidl::BytePart(&encoded_bytes[0],
static_cast<uint32_t>(encoded_bytes.size()),
static_cast<uint32_t>(encoded_bytes.size())));
auto decode_result = fidl::Decode(std::move(encoded_msg));
EXPECT_STREQ(decode_result.error,
"xunion with zero as ordinal must be empty");
EXPECT_EQ(decode_result.status, ZX_ERR_INVALID_ARGS);
}