blob: 4f1da4d243d1a35bca95ceb355d21a80455b499a [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define PACKET_TESTING
#include "packet/parser/test/big_endian_test_packets.h"
#include "packet/parser/test/test_packets.h"
#include <gtest/gtest.h>
#include <forward_list>
#include <memory>
#include "os/log.h"
#include "packet/bit_inserter.h"
#include "packet/parser/test/six_bytes.h"
#include "packet/raw_builder.h"
using ::bluetooth::packet::BitInserter;
using ::bluetooth::packet::kLittleEndian;
using ::bluetooth::packet::RawBuilder;
using ::bluetooth::packet::parser::test::SixBytes;
using std::vector;
namespace {
vector<uint8_t> child_two_two_three = {
0x20 /* Reserved : 4, FourBits::TWO */,
0x03 /* FourBits::THREE, Reserved : 4 */,
};
vector<uint8_t> child = {
0x12 /* fixed */, 0x02 /* Size of the payload */, 0xa1 /* First byte of the payload */, 0xa2, 0xb1 /* footer */,
};
vector<uint8_t> child_with_six_bytes = {
0x34 /* TwoBytes */,
0x12,
0xa1 /* First byte of the six_bytes */,
0xa2,
0xa3,
0xa4,
0xa5,
0xa6,
0xb1 /* Second six_bytes*/,
0xb2,
0xb3,
0xb4,
0xb5,
0xb6,
};
} // namespace
namespace bluetooth {
namespace packet {
namespace parser {
using namespace test;
TEST(GeneratedPacketTest, testChildTwoTwoThree) {
auto packet = ChildTwoTwoThreeBuilder::Create();
ASSERT_EQ(child_two_two_three.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(packet_bytes->size(), child_two_two_three.size());
for (size_t i = 0; i < child_two_two_three.size(); i++) {
ASSERT_EQ(packet_bytes->at(i), child_two_two_three[i]);
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
ParentView wrong_view = ParentView::Create(packet_bytes_view);
ASSERT_FALSE(wrong_view.IsValid());
ParentTwoView parent_view = ParentTwoView::Create(packet_bytes_view);
ASSERT_TRUE(parent_view.IsValid());
ASSERT_EQ(FourBits::TWO, parent_view.GetFourBits());
ChildTwoTwoView child_view = ChildTwoTwoView::Create(parent_view);
ASSERT_TRUE(child_view.IsValid());
ASSERT_EQ(FourBits::THREE, child_view.GetMoreBits());
ChildTwoTwoThreeView grandchild_view = ChildTwoTwoThreeView::Create(child_view);
ASSERT_TRUE(grandchild_view.IsValid());
}
TEST(GeneratedPacketTest, testChild) {
uint16_t field_name = 0xa2a1;
uint8_t footer = 0xb1;
auto packet = ChildBuilder::Create(field_name, footer);
ASSERT_EQ(child.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(packet_bytes->size(), child.size());
for (size_t i = 0; i < child.size(); i++) {
ASSERT_EQ(packet_bytes->at(i), child[i]);
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
ParentView parent_view = ParentView::Create(packet_bytes_view);
ASSERT_TRUE(parent_view.IsValid());
auto payload = parent_view.GetPayload();
ASSERT_EQ(child[1 /* skip fixed field */], payload.size());
for (size_t i = 0; i < payload.size(); i++) {
ASSERT_EQ(child[i + 2 /* fixed & size */], payload[i]);
}
ChildView child_view = ChildView::Create(parent_view);
ASSERT_TRUE(child_view.IsValid());
ASSERT_EQ(field_name, child_view.GetFieldName());
}
TEST(GeneratedPacketTest, testValidateWayTooSmall) {
std::vector<uint8_t> too_small_bytes = {0x34};
auto too_small = std::make_shared<std::vector<uint8_t>>(too_small_bytes.begin(), too_small_bytes.end());
ParentWithSixBytesView invalid_parent = ParentWithSixBytesView::Create(PacketView<kLittleEndian>(too_small));
ASSERT_FALSE(invalid_parent.IsValid());
ChildWithSixBytesView invalid =
ChildWithSixBytesView::Create(ParentWithSixBytesView::Create(PacketView<kLittleEndian>(too_small)));
ASSERT_FALSE(invalid.IsValid());
}
TEST(GeneratedPacketTest, testValidateTooSmall) {
std::vector<uint8_t> too_small_bytes = {0x34, 0x12, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11};
auto too_small = std::make_shared<std::vector<uint8_t>>(too_small_bytes.begin(), too_small_bytes.end());
ParentWithSixBytesView valid_parent = ParentWithSixBytesView::Create(PacketView<kLittleEndian>(too_small));
ASSERT_TRUE(valid_parent.IsValid());
ChildWithSixBytesView invalid =
ChildWithSixBytesView::Create(ParentWithSixBytesView::Create(PacketView<kLittleEndian>(too_small)));
ASSERT_FALSE(invalid.IsValid());
}
TEST(GeneratedPacketTest, testValidateJustRight) {
std::vector<uint8_t> just_right_bytes = {0x34, 0x12, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
auto just_right = std::make_shared<std::vector<uint8_t>>(just_right_bytes.begin(), just_right_bytes.end());
ChildWithSixBytesView valid =
ChildWithSixBytesView::Create(ParentWithSixBytesView::Create(PacketView<kLittleEndian>(just_right)));
ASSERT_TRUE(valid.IsValid());
}
TEST(GeneratedPacketTest, testValidateTooBig) {
std::vector<uint8_t> too_big_bytes = {0x34, 0x12, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x20};
auto too_big = std::make_shared<std::vector<uint8_t>>(too_big_bytes.begin(), too_big_bytes.end());
ChildWithSixBytesView lenient =
ChildWithSixBytesView::Create(ParentWithSixBytesView::Create(PacketView<kLittleEndian>(too_big)));
ASSERT_TRUE(lenient.IsValid());
}
TEST(GeneratedPacketTest, testValidateDeath) {
auto packet = ChildTwoTwoThreeBuilder::Create();
ASSERT_EQ(child_two_two_three.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(packet_bytes->size(), child_two_two_three.size());
for (size_t i = 0; i < child_two_two_three.size(); i++) {
ASSERT_EQ(packet_bytes->at(i), child_two_two_three[i]);
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
ParentView wrong_view = ParentView::Create(packet_bytes_view);
ASSERT_DEATH(wrong_view.GetPayload(), "validated");
}
TEST(GeneratedPacketTest, testValidatedParentDeath) {
uint16_t field_name = 0xa2a1;
uint8_t footer = 0xb1;
auto packet = ChildBuilder::Create(field_name, footer);
ASSERT_EQ(child.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(packet_bytes->size(), child.size());
for (size_t i = 0; i < child.size(); i++) {
ASSERT_EQ(packet_bytes->at(i), child[i]);
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
ParentView parent_view = ParentView::Create(packet_bytes_view);
ASSERT_TRUE(parent_view.IsValid());
auto payload = parent_view.GetPayload();
ASSERT_EQ(child[1 /* skip fixed field */], payload.size());
for (size_t i = 0; i < payload.size(); i++) {
ASSERT_EQ(child[i + 2 /* fixed & size */], payload[i]);
}
ChildView child_view = ChildView::Create(parent_view);
ASSERT_DEATH(child_view.GetFieldName(), "validated");
}
vector<uint8_t> middle_four_bits = {
0x95, // low_two = ONE, next_four = FIVE, straddle = TEN
0x8a, // straddle = TEN, four_more = TWO, high_two = TWO
};
TEST(GeneratedPacketTest, testMiddleFourBitsPacket) {
TwoBits low_two = TwoBits::ONE;
FourBits next_four = FourBits::FIVE;
FourBits straddle = FourBits::TEN;
FourBits four_more = FourBits::TWO;
TwoBits high_two = TwoBits::TWO;
auto packet = MiddleFourBitsBuilder::Create(low_two, next_four, straddle, four_more, high_two);
ASSERT_EQ(middle_four_bits.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(packet_bytes->size(), middle_four_bits.size());
for (size_t i = 0; i < middle_four_bits.size(); i++) {
ASSERT_EQ(packet_bytes->at(i), middle_four_bits[i]);
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
MiddleFourBitsView view = MiddleFourBitsView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
ASSERT_EQ(low_two, view.GetLowTwo());
ASSERT_EQ(next_four, view.GetNextFour());
ASSERT_EQ(straddle, view.GetStraddle());
ASSERT_EQ(four_more, view.GetFourMore());
ASSERT_EQ(high_two, view.GetHighTwo());
}
TEST(GeneratedPacketTest, testChildWithSixBytes) {
SixBytes six_bytes_a{{0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6}};
SixBytes six_bytes_b{{0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6}};
auto packet = ChildWithSixBytesBuilder::Create(six_bytes_a, six_bytes_b);
ASSERT_EQ(child_with_six_bytes.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(packet_bytes->size(), child_with_six_bytes.size());
for (size_t i = 0; i < child_with_six_bytes.size(); i++) {
ASSERT_EQ(packet_bytes->at(i), child_with_six_bytes[i]);
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
ParentWithSixBytesView parent_view = ParentWithSixBytesView::Create(packet_bytes_view);
ASSERT_TRUE(parent_view.IsValid());
ASSERT_EQ(six_bytes_a, parent_view.GetSixBytes());
ChildWithSixBytesView child_view = ChildWithSixBytesView::Create(parent_view);
ASSERT_TRUE(child_view.IsValid());
ASSERT_EQ(six_bytes_a, child_view.GetSixBytes());
ASSERT_EQ(six_bytes_a, ((ParentWithSixBytesView)child_view).GetSixBytes());
ASSERT_EQ(six_bytes_b, child_view.GetChildSixBytes());
}
namespace {
vector<uint8_t> parent_with_sum = {
0x11 /* TwoBytes */, 0x12, 0x21 /* Sum Bytes */, 0x22, 0x43 /* Sum, excluding TwoBytes */, 0x00,
};
} // namespace
TEST(GeneratedPacketTest, testParentWithSum) {
uint16_t two_bytes = 0x1211;
uint16_t sum_bytes = 0x2221;
auto packet = ParentWithSumBuilder::Create(two_bytes, sum_bytes, std::make_unique<packet::RawBuilder>());
ASSERT_EQ(parent_with_sum.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(packet_bytes->size(), parent_with_sum.size());
for (size_t i = 0; i < parent_with_sum.size(); i++) {
ASSERT_EQ(packet_bytes->at(i), parent_with_sum[i]);
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
ParentWithSumView parent_view = ParentWithSumView::Create(packet_bytes_view);
ASSERT_TRUE(parent_view.IsValid());
ASSERT_EQ(two_bytes, parent_view.GetTwoBytes());
// Corrupt checksum
packet_bytes->back()++;
PacketView<kLittleEndian> corrupted_bytes_view(packet_bytes);
ParentWithSumView corrupted_view = ParentWithSumView::Create(corrupted_bytes_view);
ASSERT_FALSE(corrupted_view.IsValid());
}
namespace {
vector<uint8_t> child_with_nested_sum = {
0x11 /* TwoBytes */,
0x12,
0x21 /* Sum Bytes */,
0x22,
0x31 /* More Bytes */,
0x32,
0x33,
0x34,
0xca /* Nested Sum */,
0x00,
0xd7 /* Sum, excluding TwoBytes */,
0x01,
};
} // namespace
TEST(GeneratedPacketTest, testChildWithNestedSum) {
uint16_t two_bytes = 0x1211;
uint16_t sum_bytes = 0x2221;
uint32_t more_bytes = 0x34333231;
auto packet = ChildWithNestedSumBuilder::Create(two_bytes, sum_bytes, more_bytes);
ASSERT_EQ(child_with_nested_sum.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(packet_bytes->size(), child_with_nested_sum.size());
for (size_t i = 0; i < child_with_nested_sum.size(); i++) {
ASSERT_EQ(packet_bytes->at(i), child_with_nested_sum[i]);
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
ParentWithSumView parent_view = ParentWithSumView::Create(packet_bytes_view);
ASSERT_TRUE(parent_view.IsValid());
ASSERT_EQ(two_bytes, parent_view.GetTwoBytes());
ChildWithNestedSumView child_view = ChildWithNestedSumView::Create(parent_view);
ASSERT_TRUE(child_view.IsValid());
ASSERT_EQ(more_bytes, child_view.GetMoreBytes());
}
namespace {
vector<uint8_t> parent_size_modifier = {
0x02 /* Size */,
0x11 /* TwoBytes */,
0x12,
};
} // namespace
TEST(GeneratedPacketTest, testParentSizeModifier) {
uint16_t two_bytes = 0x1211;
auto packet = ParentSizeModifierBuilder::Create(std::make_unique<RawBuilder>(), two_bytes);
ASSERT_EQ(parent_size_modifier.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(parent_size_modifier.size(), packet_bytes->size());
for (size_t i = 0; i < parent_size_modifier.size(); i++) {
ASSERT_EQ(parent_size_modifier[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
ParentSizeModifierView parent_view = ParentSizeModifierView::Create(packet_bytes_view);
ASSERT_TRUE(parent_view.IsValid());
ASSERT_EQ(two_bytes, parent_view.GetTwoBytes());
}
namespace {
vector<uint8_t> child_size_modifier = {
0x06 /* PayloadSize (TwoBytes + MoreBytes)*/,
0x31 /* MoreBytes */,
0x32,
0x33,
0x34,
0x11 /* TwoBytes = 0x1211 */,
0x12,
};
} // namespace
TEST(GeneratedPacketTest, testChildSizeModifier) {
uint16_t two_bytes = 0x1211;
uint32_t more_bytes = 0x34333231;
auto packet = ChildSizeModifierBuilder::Create(more_bytes);
ASSERT_EQ(child_size_modifier.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(child_size_modifier.size(), packet_bytes->size());
for (size_t i = 0; i < child_size_modifier.size(); i++) {
ASSERT_EQ(child_size_modifier[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
ParentSizeModifierView parent_view = ParentSizeModifierView::Create(packet_bytes_view);
ASSERT_TRUE(parent_view.IsValid());
ASSERT_EQ(two_bytes, parent_view.GetTwoBytes());
ChildSizeModifierView child_view = ChildSizeModifierView::Create(parent_view);
ASSERT_TRUE(child_view.IsValid());
ASSERT_EQ(more_bytes, child_view.GetMoreBytes());
}
namespace {
vector<uint8_t> fixed_array_enum{
0x01, // ONE
0x00,
0x02, // TWO
0x00,
0x01, // ONE_TWO
0x02,
0x02, // TWO_THREE
0x03,
0xff, // FFFF
0xff,
};
}
TEST(GeneratedPacketTest, testFixedArrayEnum) {
std::array<ForArrays, 5> fixed_array{
{ForArrays::ONE, ForArrays::TWO, ForArrays::ONE_TWO, ForArrays::TWO_THREE, ForArrays::FFFF}};
auto packet = FixedArrayEnumBuilder::Create(fixed_array);
ASSERT_EQ(fixed_array_enum.size(), packet->size());
// Verify that the packet is independent from the array.
std::array<ForArrays, 5> copy_array(fixed_array);
fixed_array[1] = ForArrays::ONE;
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(fixed_array_enum.size(), packet_bytes->size());
for (size_t i = 0; i < fixed_array_enum.size(); i++) {
ASSERT_EQ(fixed_array_enum[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = FixedArrayEnumView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetEnumArray();
ASSERT_EQ(copy_array.size(), array.size());
for (size_t i = 0; i < copy_array.size(); i++) {
ASSERT_EQ(array[i], copy_array[i]);
}
}
namespace {
vector<uint8_t> sized_array_enum{
0x0a, // _size_
0x00,
0x01, // ONE
0x00,
0x02, // TWO
0x00,
0x01, // ONE_TWO
0x02,
0x02, // TWO_THREE
0x03,
0xff, // FFFF
0xff,
};
}
TEST(GeneratedPacketTest, testSizedArrayEnum) {
std::vector<ForArrays> sized_array{
{ForArrays::ONE, ForArrays::TWO, ForArrays::ONE_TWO, ForArrays::TWO_THREE, ForArrays::FFFF}};
auto packet = SizedArrayEnumBuilder::Create(sized_array);
ASSERT_EQ(sized_array_enum.size(), packet->size());
// Copy the original vector and modify it to make sure the packet is independent.
std::vector<ForArrays> copy_array(sized_array);
sized_array[1] = ForArrays::ONE;
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(sized_array_enum.size(), packet_bytes->size());
for (size_t i = 0; i < sized_array_enum.size(); i++) {
ASSERT_EQ(sized_array_enum[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = SizedArrayEnumView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetEnumArray();
ASSERT_EQ(copy_array.size(), array.size());
for (size_t i = 0; i < copy_array.size(); i++) {
ASSERT_EQ(array[i], copy_array[i]);
}
}
namespace {
vector<uint8_t> count_array_enum{
0x03, // _count_
0x01, // ONE
0x00,
0x02, // TWO_THREE
0x03,
0xff, // FFFF
0xff,
};
}
TEST(GeneratedPacketTest, testCountArrayEnum) {
std::vector<ForArrays> count_array{{ForArrays::ONE, ForArrays::TWO_THREE, ForArrays::FFFF}};
auto packet = CountArrayEnumBuilder::Create(count_array);
ASSERT_EQ(count_array_enum.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(count_array_enum.size(), packet_bytes->size());
for (size_t i = 0; i < count_array_enum.size(); i++) {
ASSERT_EQ(count_array_enum[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = CountArrayEnumView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetEnumArray();
ASSERT_EQ(count_array.size(), array.size());
for (size_t i = 0; i < count_array.size(); i++) {
ASSERT_EQ(array[i], count_array[i]);
}
}
TEST(GeneratedPacketTest, testFixedSizeByteArray) {
constexpr std::size_t byte_array_size = 32;
std::array<uint8_t, byte_array_size> byte_array;
for (uint8_t i = 0; i < byte_array_size; i++) byte_array[i] = i;
constexpr int word_array_size = 8;
std::array<uint32_t, word_array_size> word_array;
for (uint32_t i = 0; i < word_array_size; i++) word_array[i] = i;
auto packet = PacketWithFixedArraysOfBytesBuilder::Create(byte_array, word_array);
ASSERT_EQ(2 * (256 / 8), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(byte_array_size + word_array_size * sizeof(uint32_t), packet_bytes->size());
for (size_t i = 0; i < byte_array_size; i++) {
ASSERT_EQ(byte_array[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = PacketWithFixedArraysOfBytesView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetFixed256bitInBytes();
ASSERT_EQ(byte_array.size(), array.size());
for (size_t i = 0; i < array.size(); i++) {
ASSERT_EQ(array[i], byte_array[i]);
}
auto decoded_word_array = view.GetFixed256bitInWords();
ASSERT_EQ(word_array.size(), decoded_word_array.size());
for (size_t i = 0; i < decoded_word_array.size(); i++) {
ASSERT_EQ(word_array[i], decoded_word_array[i]);
}
}
vector<uint8_t> one_variable{
0x03, 'o', 'n', 'e', // "one"
};
TEST(GeneratedPacketTest, testOneVariableField) {
Variable variable_one{"one"};
auto packet = OneVariableBuilder::Create(variable_one);
ASSERT_EQ(one_variable.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(one_variable.size(), packet_bytes->size());
for (size_t i = 0; i < one_variable.size(); i++) {
ASSERT_EQ(one_variable[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto one = view.GetOne();
ASSERT_EQ(one->data, variable_one.data);
}
vector<uint8_t> fou_variable{
0x04, 'f', 'o', 'u', // too short
};
TEST(GeneratedPacketTest, testOneVariableFieldTooShort) {
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>(fou_variable);
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto one = view.GetOne();
ASSERT_EQ(one, nullptr);
}
vector<uint8_t> sized_array_variable{
0x0e, // _size_
0x03, 'o', 'n', 'e', // "one"
0x03, 't', 'w', 'o', // "two"
0x05, 't', 'h', 'r', 'e', 'e', // "three"
};
TEST(GeneratedPacketTest, testSizedArrayVariableLength) {
std::vector<Variable> sized_array;
sized_array.emplace_back("one");
sized_array.emplace_back("two");
sized_array.emplace_back("three");
auto packet = SizedArrayVariableBuilder::Create(sized_array);
ASSERT_EQ(sized_array_variable.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(sized_array_variable.size(), packet_bytes->size());
for (size_t i = 0; i < sized_array_variable.size(); i++) {
ASSERT_EQ(sized_array_variable[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = SizedArrayVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetVariableArray();
ASSERT_EQ(sized_array.size(), array.size());
for (size_t i = 0; i < sized_array.size(); i++) {
ASSERT_EQ(array[i].data, sized_array[i].data);
}
}
vector<uint8_t> sized_array_variable_too_short{
0x0e, // _size_
0x03, 'o', 'n', 'e', // "one"
0x03, 't', 'w', 'o', // "two"
0x06, 't', 'h', 'r', 'e', 'e', // "three" needs another letter to be length 6
};
TEST(GeneratedPacketTest, testSizedArrayVariableLengthLastBad) {
std::vector<Variable> sized_array;
sized_array.emplace_back("one");
sized_array.emplace_back("two");
std::shared_ptr<std::vector<uint8_t>> packet_bytes =
std::make_shared<std::vector<uint8_t>>(sized_array_variable_too_short);
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = SizedArrayVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetVariableArray();
ASSERT_EQ(sized_array.size(), array.size());
for (size_t i = 0; i < sized_array.size(); i++) {
ASSERT_EQ(array[i].data, sized_array[i].data);
}
}
vector<uint8_t> sized_array_variable_first_too_short{
0x0e, // _size_
0x02, 'o', 'n', 'e', // "on"
0x03, 't', 'w', 'o', // "two"
0x05, 't', 'h', 'r', 'e', 'e', // "three"
};
TEST(GeneratedPacketTest, testSizedArrayVariableLengthFirstBad) {
std::vector<Variable> sized_array;
sized_array.emplace_back("on");
std::shared_ptr<std::vector<uint8_t>> packet_bytes =
std::make_shared<std::vector<uint8_t>>(sized_array_variable_first_too_short);
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = SizedArrayVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetVariableArray();
ASSERT_EQ(sized_array.size(), array.size());
for (size_t i = 0; i < sized_array.size(); i++) {
ASSERT_EQ(array[i].data, sized_array[i].data);
}
}
vector<uint8_t> fixed_array_variable{
0x03, 'o', 'n', 'e', // "one"
0x03, 't', 'w', 'o', // "two"
0x05, 't', 'h', 'r', 'e', 'e', // "three"
0x04, 'f', 'o', 'u', 'r', // "four"
0x04, 'f', 'i', 'v', 'e', // "five"
};
TEST(GeneratedPacketTest, testFixedArrayVariableLength) {
std::array<Variable, 5> fixed_array{std::string("one"), std::string("two"), std::string("three"), std::string("four"),
std::string("five")};
auto packet = FixedArrayVariableBuilder::Create(fixed_array);
ASSERT_EQ(fixed_array_variable.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(fixed_array_variable.size(), packet_bytes->size());
for (size_t i = 0; i < fixed_array_variable.size(); i++) {
ASSERT_EQ(fixed_array_variable[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = FixedArrayVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetVariableArray();
ASSERT_EQ(fixed_array.size(), array.size());
for (size_t i = 0; i < fixed_array.size(); i++) {
ASSERT_EQ(array[i].data, fixed_array[i].data);
}
}
vector<uint8_t> fixed_array_variable_too_short{
0x03, 'o', 'n', 'e', // "one"
0x03, 't', 'w', 'o', // "two"
0x05, 't', 'h', 'r', 'e', 'e', // "three"
0x04, 'f', 'o', 'u', 'r', // "four"
0x05, 'f', 'i', 'v', 'e', // "five"
};
TEST(GeneratedPacketTest, testFixedArrayVariableLengthTooShort) {
std::array<Variable, 5> fixed_array{std::string("one"), std::string("two"), std::string("three"),
std::string("four")};
std::shared_ptr<std::vector<uint8_t>> packet_bytes =
std::make_shared<std::vector<uint8_t>>(fixed_array_variable_too_short);
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = FixedArrayVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetVariableArray();
ASSERT_EQ(fixed_array.size(), array.size());
for (size_t i = 0; i < fixed_array.size(); i++) {
ASSERT_EQ(array[i].data, fixed_array[i].data);
}
}
vector<uint8_t> count_array_variable{
0x04, // _count_
0x03, 'o', 'n', 'e', // "one"
0x03, 't', 'w', 'o', // "two"
0x05, 't', 'h', 'r', 'e', 'e', // "three"
0x04, 'f', 'o', 'u', 'r', // "four"
};
TEST(GeneratedPacketTest, testCountArrayVariableLength) {
std::vector<Variable> count_array;
count_array.emplace_back("one");
count_array.emplace_back("two");
count_array.emplace_back("three");
count_array.emplace_back("four");
auto packet = CountArrayVariableBuilder::Create(count_array);
ASSERT_EQ(count_array_variable.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(count_array_variable.size(), packet_bytes->size());
for (size_t i = 0; i < count_array_variable.size(); i++) {
ASSERT_EQ(count_array_variable[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = CountArrayVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetVariableArray();
ASSERT_EQ(count_array.size(), array.size());
for (size_t i = 0; i < count_array.size(); i++) {
ASSERT_EQ(array[i].data, count_array[i].data);
}
}
vector<uint8_t> count_array_variable_extra{
0x04, // _count_
0x03, 'o', 'n', 'e', // "one"
0x03, 't', 'w', 'o', // "two"
0x05, 't', 'h', 'r', 'e', 'e', // "three"
0x04, 'f', 'o', 'u', 'r', // "four"
0x04, 'x', 't', 'r', 'a', // "xtra"
};
TEST(GeneratedPacketTest, testCountArrayVariableLengthExtraData) {
std::vector<Variable> count_array;
count_array.emplace_back("one");
count_array.emplace_back("two");
count_array.emplace_back("three");
count_array.emplace_back("four");
std::shared_ptr<std::vector<uint8_t>> packet_bytes =
std::make_shared<std::vector<uint8_t>>(count_array_variable_extra);
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = CountArrayVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetVariableArray();
ASSERT_EQ(count_array.size(), array.size());
for (size_t i = 0; i < count_array.size(); i++) {
ASSERT_EQ(array[i].data, count_array[i].data);
}
}
vector<uint8_t> count_array_variable_too_few{
0x04, // _count_
0x03, 'o', 'n', 'e', // "one"
0x03, 't', 'w', 'o', // "two"
0x05, 't', 'h', 'r', 'e', 'e', // "three"
};
TEST(GeneratedPacketTest, testCountArrayVariableLengthMissingData) {
std::vector<Variable> count_array;
count_array.emplace_back("one");
count_array.emplace_back("two");
count_array.emplace_back("three");
std::shared_ptr<std::vector<uint8_t>> packet_bytes =
std::make_shared<std::vector<uint8_t>>(count_array_variable_too_few);
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = CountArrayVariableView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetVariableArray();
ASSERT_EQ(count_array.size(), array.size());
for (size_t i = 0; i < count_array.size(); i++) {
ASSERT_EQ(array[i].data, count_array[i].data);
}
}
vector<uint8_t> one_struct{
0x01, 0x02, 0x03, // id = 0x01, count = 0x0302
};
TEST(GeneratedPacketTest, testOneStruct) {
TwoRelatedNumbers trn;
trn.id_ = 1;
trn.count_ = 0x0302;
auto packet = OneStructBuilder::Create(trn);
ASSERT_EQ(one_struct.size(), packet->size());
// Copy the original struct, then modify it to verify independence from the packet.
TwoRelatedNumbers copy_trn(trn);
trn.id_ = 2;
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(one_struct.size(), packet_bytes->size());
for (size_t i = 0; i < one_struct.size(); i++) {
ASSERT_EQ(one_struct[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto one = view.GetOne();
ASSERT_EQ(one.id_, copy_trn.id_);
ASSERT_EQ(one.count_, copy_trn.count_);
}
vector<uint8_t> two_structs{
0x01, 0x01, 0x02, // id, id * 0x0201
0x02, 0x02, 0x04,
};
TEST(GeneratedPacketTest, testTwoStructs) {
std::vector<TwoRelatedNumbers> count_array;
for (uint8_t i = 1; i < 3; i++) {
TwoRelatedNumbers trn;
trn.id_ = i;
trn.count_ = 0x0201 * i;
count_array.push_back(trn);
}
auto packet = TwoStructsBuilder::Create(count_array[0], count_array[1]);
ASSERT_EQ(two_structs.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(two_structs.size(), packet_bytes->size());
for (size_t i = 0; i < two_structs.size(); i++) {
ASSERT_EQ(two_structs[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = TwoStructsView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto one = view.GetOne();
ASSERT_EQ(one.id_, count_array[0].id_);
ASSERT_EQ(one.count_, count_array[0].count_);
auto two = view.GetTwo();
ASSERT_EQ(two.id_, count_array[1].id_);
ASSERT_EQ(two.count_, count_array[1].count_);
}
vector<uint8_t> array_or_vector_of_struct{
0x04, // _count_
0x01, 0x01, 0x02, // id, id * 0x0201
0x02, 0x02, 0x04, 0x03, 0x03, 0x06, 0x04, 0x04, 0x08,
};
TEST(GeneratedPacketTest, testVectorOfStruct) {
std::vector<TwoRelatedNumbers> count_array;
for (uint8_t i = 1; i < 5; i++) {
TwoRelatedNumbers trn;
trn.id_ = i;
trn.count_ = 0x0201 * i;
count_array.push_back(trn);
}
// Make a copy
std::vector<TwoRelatedNumbers> copy_array(count_array);
auto packet = VectorOfStructBuilder::Create(count_array);
// Change the original vector to make sure a copy was made.
count_array[0].id_ = count_array[0].id_ + 1;
ASSERT_EQ(array_or_vector_of_struct.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(array_or_vector_of_struct.size(), packet_bytes->size());
for (size_t i = 0; i < array_or_vector_of_struct.size(); i++) {
ASSERT_EQ(array_or_vector_of_struct[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = VectorOfStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetArray();
ASSERT_EQ(copy_array.size(), array.size());
for (size_t i = 0; i < copy_array.size(); i++) {
ASSERT_EQ(array[i].id_, copy_array[i].id_);
ASSERT_EQ(array[i].count_, copy_array[i].count_);
}
}
TEST(GeneratedPacketTest, testArrayOfStruct) {
std::array<TwoRelatedNumbers, 4> count_array;
for (uint8_t i = 1; i < 5; i++) {
TwoRelatedNumbers trn;
trn.id_ = i;
trn.count_ = 0x0201 * i;
count_array[i - 1] = trn;
}
// Make a copy
std::array<TwoRelatedNumbers, 4> copy_array(count_array);
auto packet = ArrayOfStructBuilder::Create(4, count_array);
// Change the original vector to make sure a copy was made.
count_array[0].id_ = count_array[0].id_ + 1;
ASSERT_EQ(array_or_vector_of_struct.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(array_or_vector_of_struct.size(), packet_bytes->size());
for (size_t i = 0; i < array_or_vector_of_struct.size(); i++) {
ASSERT_EQ(array_or_vector_of_struct[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = ArrayOfStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetArray();
ASSERT_EQ(copy_array.size(), array.size());
for (size_t i = 0; i < copy_array.size(); i++) {
ASSERT_EQ(array[i].id_, copy_array[i].id_);
ASSERT_EQ(array[i].count_, copy_array[i].count_);
}
}
vector<uint8_t> one_fixed_types_struct{
0x05, // four_bits = FIVE, reserved
0xf3, // _fixed_
0x0d, // id = 0x0d
0x01, 0x02, 0x03, // array = { 1, 2, 3}
0x06, 0x01, // example_checksum
0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, // six_bytes
};
TEST(GeneratedPacketTest, testOneFixedTypesStruct) {
StructWithFixedTypes swf;
swf.four_bits_ = FourBits::FIVE;
swf.id_ = 0x0d;
swf.array_ = {{0x01, 0x02, 0x03}};
swf.six_bytes_ = SixBytes{{0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6}};
auto packet = OneFixedTypesStructBuilder::Create(swf);
ASSERT_EQ(one_fixed_types_struct.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(one_fixed_types_struct.size(), packet_bytes->size());
for (size_t i = 0; i < one_fixed_types_struct.size(); i++) {
ASSERT_EQ(one_fixed_types_struct[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneFixedTypesStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto one = view.GetOne();
ASSERT_EQ(one.four_bits_, swf.four_bits_);
ASSERT_EQ(one.id_, swf.id_);
ASSERT_EQ(one.array_, swf.array_);
ASSERT_EQ(one.six_bytes_, swf.six_bytes_);
}
vector<uint8_t> array_of_struct_and_another{
0x03, // _count_
0x01, 0x01, 0x02, // id, id * 0x0201
0x02, 0x02, 0x04, // 2
0x03, 0x03, 0x06, // 3
0x04, 0x04, 0x08, // Another
};
TEST(GeneratedPacketTest, testArrayOfStructAndAnother) {
std::vector<TwoRelatedNumbers> count_array;
for (uint8_t i = 1; i < 4; i++) {
TwoRelatedNumbers trn;
trn.id_ = i;
trn.count_ = 0x0201 * i;
count_array.push_back(trn);
}
TwoRelatedNumbers another;
another.id_ = 4;
another.count_ = 0x0201 * 4;
auto packet = ArrayOfStructAndAnotherBuilder::Create(count_array, another);
ASSERT_EQ(array_or_vector_of_struct.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(array_of_struct_and_another.size(), packet_bytes->size());
for (size_t i = 0; i < array_of_struct_and_another.size(); i++) {
ASSERT_EQ(array_of_struct_and_another[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = ArrayOfStructAndAnotherView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetArray();
ASSERT_EQ(count_array.size(), array.size());
for (size_t i = 0; i < count_array.size(); i++) {
ASSERT_EQ(array[i].id_, count_array[i].id_);
ASSERT_EQ(array[i].count_, count_array[i].count_);
}
auto nother = view.GetAnother();
ASSERT_EQ(nother.id_, another.id_);
ASSERT_EQ(nother.count_, another.count_);
}
DEFINE_AND_INSTANTIATE_OneArrayOfStructAndAnotherStructReflectionTest(array_of_struct_and_another);
TEST(GeneratedPacketTest, testOneArrayOfStructAndAnotherStruct) {
std::shared_ptr<std::vector<uint8_t>> packet_bytes =
std::make_shared<std::vector<uint8_t>>(array_of_struct_and_another);
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneArrayOfStructAndAnotherStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto one = view.GetOne();
ASSERT_EQ(one.array_.size(), 3);
ASSERT_EQ(one.another_.id_, 4);
ASSERT_EQ(one.another_.count_, 0x0804);
}
vector<uint8_t> sized_array_of_struct_and_another{
0x09, // _size_
0x01, 0x01, 0x02, // id, id * 0x0201
0x02, 0x02, 0x04, // 2
0x03, 0x03, 0x06, // 3
0x04, 0x04, 0x08, // Another
};
DEFINE_AND_INSTANTIATE_OneSizedArrayOfStructAndAnotherStructReflectionTest(sized_array_of_struct_and_another);
vector<uint8_t> bit_field_group_packet{
// seven_bits_ = 0x77, straddle_ = 0x5, five_bits_ = 0x15
0xf7, // 0x77 | (0x5 & 0x1) << 7
0xaa, // 0x15 << 3 | (0x5 >> 1)
};
TEST(GeneratedPacketTest, testBitFieldGroupPacket) {
uint8_t seven_bits = 0x77;
uint8_t straddle = 0x5;
uint8_t five_bits = 0x15;
auto packet = BitFieldGroupPacketBuilder::Create(seven_bits, straddle, five_bits);
ASSERT_EQ(bit_field_group_packet.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(bit_field_group_packet.size(), packet_bytes->size());
for (size_t i = 0; i < bit_field_group_packet.size(); i++) {
ASSERT_EQ(bit_field_group_packet[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = BitFieldGroupPacketView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
ASSERT_EQ(seven_bits, view.GetSevenBits());
ASSERT_EQ(straddle, view.GetStraddle());
ASSERT_EQ(five_bits, view.GetFiveBits());
}
vector<uint8_t> bit_field_packet{
// seven_bits_ = 0x77, straddle_ = 0x5, five_bits_ = 0x15
0xf7, // 0x77 | (0x5 & 0x1) << 7
0xaa, // 0x15 << 3 | (0x5 >> 1)
};
TEST(GeneratedPacketTest, testBitFieldPacket) {
BitField bit_field;
bit_field.seven_bits_ = 0x77;
bit_field.straddle_ = 0x5;
bit_field.five_bits_ = 0x15;
auto packet = BitFieldPacketBuilder::Create(bit_field);
ASSERT_EQ(bit_field_packet.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(bit_field_packet.size(), packet_bytes->size());
for (size_t i = 0; i < bit_field_packet.size(); i++) {
ASSERT_EQ(bit_field_packet[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = BitFieldPacketView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
BitField bf = view.GetBitField();
ASSERT_EQ(bf.seven_bits_, bit_field.seven_bits_);
ASSERT_EQ(bf.straddle_, bit_field.straddle_);
ASSERT_EQ(bf.five_bits_, bit_field.five_bits_);
}
vector<uint8_t> bit_field_group_after_unsized_array_packet{
0x01, 0x02, 0x03, 0x04, // byte array
// seven_bits_ = 0x77, straddle_ = 0x5, five_bits_ = 0x15
0xf7, // 0x77 | (0x5 & 0x1) << 7
0xaa, // 0x15 << 3 | (0x5 >> 1)
};
TEST(GeneratedPacketTest, testBitFieldGroupAfterUnsizedArrayPacket) {
std::vector<uint8_t> count_array;
for (uint8_t i = 1; i < 5; i++) {
count_array.push_back(i);
}
uint8_t seven_bits = 0x77;
uint8_t straddle = 0x5;
uint8_t five_bits = 0x15;
auto packet = BitFieldGroupAfterUnsizedArrayPacketBuilder::Create(count_array, seven_bits, straddle, five_bits);
ASSERT_EQ(bit_field_group_after_unsized_array_packet.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(bit_field_group_after_unsized_array_packet.size(), packet_bytes->size());
for (size_t i = 0; i < bit_field_group_after_unsized_array_packet.size(); i++) {
ASSERT_EQ(bit_field_group_after_unsized_array_packet[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto payload_view = BitFieldGroupAfterPayloadPacketView::Create(packet_bytes_view);
ASSERT_TRUE(payload_view.IsValid());
EXPECT_EQ(seven_bits, payload_view.GetSevenBits());
EXPECT_EQ(straddle, payload_view.GetStraddle());
EXPECT_EQ(five_bits, payload_view.GetFiveBits());
auto view = BitFieldGroupAfterUnsizedArrayPacketView::Create(payload_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetArray();
ASSERT_EQ(count_array.size(), array.size());
for (size_t i = 0; i < count_array.size(); i++) {
ASSERT_EQ(array[i], count_array[i]);
}
ASSERT_EQ(seven_bits, view.GetSevenBits());
ASSERT_EQ(straddle, view.GetStraddle());
ASSERT_EQ(five_bits, view.GetFiveBits());
}
vector<uint8_t> bit_field_after_unsized_array_packet{
0x01, 0x02, 0x03, 0x04, // byte array
// seven_bits_ = 0x77, straddle_ = 0x5, five_bits_ = 0x15
0xf7, // 0x77 | (0x5 & 0x1) << 7
0xaa, // 0x15 << 3 | (0x5 >> 1)
};
TEST(GeneratedPacketTest, testBitFieldAfterUnsizedArrayPacket) {
std::vector<uint8_t> count_array;
for (uint8_t i = 1; i < 5; i++) {
count_array.push_back(i);
}
BitField bit_field;
bit_field.seven_bits_ = 0x77;
bit_field.straddle_ = 0x5;
bit_field.five_bits_ = 0x15;
auto packet = BitFieldAfterUnsizedArrayPacketBuilder::Create(count_array, bit_field);
ASSERT_EQ(bit_field_after_unsized_array_packet.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(bit_field_after_unsized_array_packet.size(), packet_bytes->size());
for (size_t i = 0; i < bit_field_after_unsized_array_packet.size(); i++) {
ASSERT_EQ(bit_field_after_unsized_array_packet[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto payload_view = BitFieldAfterPayloadPacketView::Create(packet_bytes_view);
ASSERT_TRUE(payload_view.IsValid());
BitField parent_bf = payload_view.GetBitField();
ASSERT_EQ(parent_bf.seven_bits_, bit_field.seven_bits_);
ASSERT_EQ(parent_bf.straddle_, bit_field.straddle_);
ASSERT_EQ(parent_bf.five_bits_, bit_field.five_bits_);
auto view = BitFieldAfterUnsizedArrayPacketView::Create(payload_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetArray();
ASSERT_EQ(count_array.size(), array.size());
for (size_t i = 0; i < count_array.size(); i++) {
ASSERT_EQ(array[i], count_array[i]);
}
BitField bf = view.GetBitField();
ASSERT_EQ(bf.seven_bits_, bit_field.seven_bits_);
ASSERT_EQ(bf.straddle_, bit_field.straddle_);
ASSERT_EQ(bf.five_bits_, bit_field.five_bits_);
}
vector<uint8_t> bit_field_array_packet{
0x06, // _size_(array)
// seven_bits_ = 0x77, straddle_ = 0x5, five_bits_ = 0x15
0xf7, // 0x77 | (0x5 & 0x1) << 7
0xaa, // 0x15 << 3 | (0x5 >> 1)
// seven_bits_ = 0x78, straddle_ = 0x6, five_bits_ = 0x16
0x78, // 0x78 | (0x6 & 0x1) << 7
0xb3, // 0x16 << 3 | (0x6 >> 1)
// seven_bits_ = 0x79, straddle_ = 0x7, five_bits_ = 0x17
0xf9, // 0x79 | (0x7 & 0x1) << 7
0xbb, // 0x17 << 3 | (0x7 >> 1)
};
TEST(GeneratedPacketTest, testBitFieldArrayPacket) {
std::vector<BitField> count_array;
for (size_t i = 0; i < 3; i++) {
BitField bf;
bf.seven_bits_ = 0x77 + i;
bf.straddle_ = 0x5 + i;
bf.five_bits_ = 0x15 + i;
count_array.push_back(bf);
}
auto packet = BitFieldArrayPacketBuilder::Create(count_array);
ASSERT_EQ(bit_field_array_packet.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(bit_field_array_packet.size(), packet_bytes->size());
for (size_t i = 0; i < bit_field_array_packet.size(); i++) {
ASSERT_EQ(bit_field_array_packet[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = BitFieldArrayPacketView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetArray();
ASSERT_EQ(count_array.size(), array.size());
for (size_t i = 0; i < count_array.size(); i++) {
ASSERT_EQ(array[i].seven_bits_, count_array[i].seven_bits_);
ASSERT_EQ(array[i].straddle_, count_array[i].straddle_);
ASSERT_EQ(array[i].five_bits_, count_array[i].five_bits_);
}
}
TEST(GeneratedPacketTest, testNewBitFieldArrayPacket) {
PacketView<kLittleEndian> packet_bytes_view(std::make_shared<std::vector<uint8_t>>(bit_field_array_packet));
auto view = BitFieldArrayPacketView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto packet = BitFieldArrayPacketBuilder::Create(view.GetArray());
ASSERT_EQ(bit_field_array_packet.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(*packet_bytes, bit_field_array_packet);
}
std::vector<uint8_t> child_two_two_two_ = {0x20, 0x02};
std::vector<uint8_t> child_two_two_three_ = {0x20, 0x03};
std::vector<uint8_t> child_two_two_four_ = {0x20, 0x04};
DEFINE_AND_INSTANTIATE_ParentTwoReflectionTest(child_two_two_two_, child_two_two_three_, child_two_two_four_);
DEFINE_AND_INSTANTIATE_ChildTwoTwoReflectionTest(child_two_two_two_, child_two_two_three_, child_two_two_four_);
DEFINE_AND_INSTANTIATE_ChildTwoTwoThreeReflectionTest(child_two_two_three_);
std::vector<uint8_t> one_versionless_struct_packet = {0x01};
std::vector<uint8_t> one_versioned_struct_packet = {0x02, 0x03 /* version */, 0x04, 0x05, 0x06};
std::vector<uint8_t> one_version_one_struct_packet = {0x03, 0x01 /* version */, 0x02};
std::vector<uint8_t> one_version_two_struct_packet = {0x03, 0x02 /* version */, 0x03, 0x04};
DEFINE_AND_INSTANTIATE_OneVersionlessStructPacketReflectionTest(one_versionless_struct_packet,
one_versioned_struct_packet,
one_version_one_struct_packet,
one_version_two_struct_packet);
DEFINE_AND_INSTANTIATE_OneVersionedStructPacketReflectionTest(one_versioned_struct_packet,
one_version_one_struct_packet,
one_version_two_struct_packet);
DEFINE_AND_INSTANTIATE_OneVersionOneStructPacketReflectionTest(one_version_one_struct_packet);
DEFINE_AND_INSTANTIATE_OneVersionTwoStructPacketReflectionTest(one_version_two_struct_packet);
vector<uint8_t> one_struct_be{
0x01, 0x02, 0x03, // id = 0x01, count = 0x0203
};
TEST(GeneratedPacketTest, testOneStructBe) {
TwoRelatedNumbersBe trn;
trn.id_ = 1;
trn.count_ = 0x0203;
auto packet = OneStructBeBuilder::Create(trn);
ASSERT_EQ(one_struct_be.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(one_struct_be.size(), packet_bytes->size());
for (size_t i = 0; i < one_struct_be.size(); i++) {
ASSERT_EQ(one_struct_be[i], packet_bytes->at(i));
}
PacketView<!kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneStructBeView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto one = view.GetOne();
ASSERT_EQ(one.id_, trn.id_);
ASSERT_EQ(one.count_, trn.count_);
}
vector<uint8_t> two_structs_be{
0x01, 0x01, 0x02, // id, id * 0x0102
0x02, 0x02, 0x04,
};
TEST(GeneratedPacketTest, testTwoStructsBe) {
std::vector<TwoRelatedNumbersBe> count_array;
for (uint8_t i = 1; i < 3; i++) {
TwoRelatedNumbersBe trn;
trn.id_ = i;
trn.count_ = 0x0102 * i;
count_array.push_back(trn);
}
auto packet = TwoStructsBeBuilder::Create(count_array[0], count_array[1]);
ASSERT_EQ(two_structs_be.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(two_structs_be.size(), packet_bytes->size());
for (size_t i = 0; i < two_structs_be.size(); i++) {
ASSERT_EQ(two_structs_be[i], packet_bytes->at(i));
}
PacketView<!kLittleEndian> packet_bytes_view(packet_bytes);
auto view = TwoStructsBeView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto one = view.GetOne();
ASSERT_EQ(one.id_, count_array[0].id_);
ASSERT_EQ(one.count_, count_array[0].count_);
auto two = view.GetTwo();
ASSERT_EQ(two.id_, count_array[1].id_);
ASSERT_EQ(two.count_, count_array[1].count_);
}
vector<uint8_t> array_of_struct_be{
0x04, // _count_
0x01, 0x01, 0x02, // id, id * 0x0102
0x02, 0x02, 0x04, 0x03, 0x03, 0x06, 0x04, 0x04, 0x08,
};
TEST(GeneratedPacketTest, testArrayOfStructBe) {
std::vector<TwoRelatedNumbersBe> count_array;
for (uint8_t i = 1; i < 5; i++) {
TwoRelatedNumbersBe trn;
trn.id_ = i;
trn.count_ = 0x0102 * i;
count_array.push_back(trn);
}
auto packet = ArrayOfStructBeBuilder::Create(count_array);
ASSERT_EQ(array_of_struct_be.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(array_of_struct_be.size(), packet_bytes->size());
for (size_t i = 0; i < array_of_struct_be.size(); i++) {
ASSERT_EQ(array_of_struct_be[i], packet_bytes->at(i));
}
PacketView<!kLittleEndian> packet_bytes_view(packet_bytes);
auto view = ArrayOfStructBeView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto array = view.GetArray();
ASSERT_EQ(count_array.size(), array.size());
for (size_t i = 0; i < count_array.size(); i++) {
ASSERT_EQ(array[i].id_, count_array[i].id_);
ASSERT_EQ(array[i].count_, count_array[i].count_);
}
}
vector<uint8_t> one_four_byte_struct{
0x04, // struct_type_ = FourByte
0xd1, 0xd2, 0xd3, 0xd4, // four_bytes_
};
TEST(GeneratedPacketTest, testOneFourByteStruct) {
FourByteStruct four_byte_struct;
four_byte_struct.four_bytes_ = 0xd4d3d2d1;
auto packet = OneFourByteStructBuilder::Create(four_byte_struct);
ASSERT_EQ(one_four_byte_struct.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(one_four_byte_struct.size(), packet_bytes->size());
for (size_t i = 0; i < one_four_byte_struct.size(); i++) {
ASSERT_EQ(one_four_byte_struct[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneFourByteStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
ASSERT_EQ(StructType::FOUR_BYTE, view.GetOneStruct().struct_type_);
ASSERT_EQ(four_byte_struct.four_bytes_, view.GetOneStruct().four_bytes_);
}
vector<uint8_t> generic_struct_two{
0x02, // struct_type_ = TwoByte
0x01, 0x02, // two_bytes_
};
TEST(GeneratedPacketTest, testOneGenericStructTwo) {
TwoByteStruct two_byte_struct;
two_byte_struct.two_bytes_ = 0x0201;
std::unique_ptr<TwoByteStruct> two_byte_struct_ptr = std::make_unique<TwoByteStruct>(two_byte_struct);
auto packet = OneGenericStructBuilder::Create(std::move(two_byte_struct_ptr));
ASSERT_EQ(generic_struct_two.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(generic_struct_two.size(), packet_bytes->size());
for (size_t i = 0; i < generic_struct_two.size(); i++) {
ASSERT_EQ(generic_struct_two[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneGenericStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto base_struct = view.GetBaseStruct();
ASSERT_NE(nullptr, base_struct);
ASSERT_TRUE(TwoByteStruct::IsInstance(*base_struct));
TwoByteStruct* two_byte = static_cast<TwoByteStruct*>(base_struct.get());
ASSERT_NE(nullptr, two_byte);
ASSERT_TRUE(TwoByteStruct::IsInstance(*two_byte));
ASSERT_EQ(two_byte_struct.two_bytes_, 0x0201);
uint16_t val = two_byte->two_bytes_;
ASSERT_EQ(val, 0x0201);
ASSERT_EQ(two_byte_struct.two_bytes_, ((TwoByteStruct*)base_struct.get())->two_bytes_);
}
vector<uint8_t> generic_struct_four{
0x04, // struct_type_ = FourByte
0x01, 0x02, 0x03, 0x04, // four_bytes_
};
TEST(GeneratedPacketTest, testOneGenericStructFour) {
FourByteStruct four_byte_struct;
four_byte_struct.four_bytes_ = 0x04030201;
std::unique_ptr<FourByteStruct> four_byte_struct_p = std::make_unique<FourByteStruct>(four_byte_struct);
ASSERT_EQ(four_byte_struct.four_bytes_, four_byte_struct_p->four_bytes_);
auto packet = OneGenericStructBuilder::Create(std::move(four_byte_struct_p));
ASSERT_EQ(generic_struct_four.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(generic_struct_four.size(), packet_bytes->size());
for (size_t i = 0; i < generic_struct_four.size(); i++) {
ASSERT_EQ(generic_struct_four[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneGenericStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto base_struct = view.GetBaseStruct();
ASSERT_NE(nullptr, base_struct);
ASSERT_EQ(StructType::FOUR_BYTE, base_struct->struct_type_);
ASSERT_EQ(four_byte_struct.four_bytes_, ((FourByteStruct*)base_struct.get())->four_bytes_);
}
vector<uint8_t> one_struct_array{
0x04, // struct_type_ = FourByte
0xa1, 0xa2, 0xa3, 0xa4, // four_bytes_
0x04, // struct_type_ = FourByte
0xb2, 0xb2, 0xb3, 0xb4, // four_bytes_
0x02, // struct_type_ = TwoByte
0xc3, 0xc2, // two_bytes_
0x04, // struct_type_ = TwoByte
0xd4, 0xd2, 0xd3, 0xd4, // four_bytes_
};
TEST(GeneratedPacketTest, testOneGenericStructArray) {
std::vector<std::unique_ptr<UnusedParentStruct>> parent_vector;
std::unique_ptr<FourByteStruct> fbs;
std::unique_ptr<TwoByteStruct> tbs;
fbs = std::make_unique<FourByteStruct>();
fbs->four_bytes_ = 0xa4a3a2a1;
parent_vector.push_back(std::move(fbs));
fbs = std::make_unique<FourByteStruct>();
fbs->four_bytes_ = 0xb4b3b2b2;
parent_vector.push_back(std::move(fbs));
tbs = std::make_unique<TwoByteStruct>();
tbs->two_bytes_ = 0xc2c3;
parent_vector.push_back(std::move(tbs));
fbs = std::make_unique<FourByteStruct>();
fbs->four_bytes_ = 0xd4d3d2d4;
parent_vector.push_back(std::move(fbs));
std::vector<std::unique_ptr<UnusedParentStruct>> vector_copy;
for (auto& s : parent_vector) {
if (s->struct_type_ == StructType::TWO_BYTE) {
vector_copy.push_back(std::make_unique<TwoByteStruct>(*(TwoByteStruct*)s.get()));
}
if (s->struct_type_ == StructType::FOUR_BYTE) {
vector_copy.push_back(std::make_unique<FourByteStruct>(*(FourByteStruct*)s.get()));
}
}
auto packet = OneGenericStructArrayBuilder::Create(std::move(parent_vector));
ASSERT_EQ(one_struct_array.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(one_struct_array.size(), packet_bytes->size());
for (size_t i = 0; i < one_struct_array.size(); i++) {
ASSERT_EQ(one_struct_array[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneGenericStructArrayView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto an_array = view.GetAnArray();
ASSERT_EQ(vector_copy.size(), an_array.size());
for (size_t i = 0; i < vector_copy.size(); i++) {
ASSERT_NE(nullptr, an_array[i]);
ASSERT_EQ(vector_copy[i]->struct_type_, an_array[i]->struct_type_);
if (vector_copy[i]->struct_type_ == StructType::FOUR_BYTE) {
ASSERT_EQ(FourByteStruct::Specialize(vector_copy[i].get())->four_bytes_,
FourByteStruct::Specialize(an_array[i].get())->four_bytes_);
} else {
ASSERT_EQ(TwoByteStruct::Specialize(vector_copy[i].get())->two_bytes_,
TwoByteStruct::Specialize(an_array[i].get())->two_bytes_);
}
}
}
TEST(GeneratedPacketTest, testOneGenericStructFourArray) {
std::array<std::unique_ptr<UnusedParentStruct>, 4> parent_vector;
std::unique_ptr<FourByteStruct> fbs;
std::unique_ptr<TwoByteStruct> tbs;
fbs = std::make_unique<FourByteStruct>();
fbs->four_bytes_ = 0xa4a3a2a1;
parent_vector[0] = std::move(fbs);
fbs = std::make_unique<FourByteStruct>();
fbs->four_bytes_ = 0xb4b3b2b2;
parent_vector[1] = std::move(fbs);
tbs = std::make_unique<TwoByteStruct>();
tbs->two_bytes_ = 0xc2c3;
parent_vector[2] = std::move(tbs);
fbs = std::make_unique<FourByteStruct>();
fbs->four_bytes_ = 0xd4d3d2d4;
parent_vector[3] = std::move(fbs);
std::array<std::unique_ptr<UnusedParentStruct>, 4> vector_copy;
size_t index = 0;
for (auto& s : parent_vector) {
if (s->struct_type_ == StructType::TWO_BYTE) {
vector_copy[index] = std::make_unique<TwoByteStruct>(*(TwoByteStruct*)s.get());
}
if (s->struct_type_ == StructType::FOUR_BYTE) {
vector_copy[index] = std::make_unique<FourByteStruct>(*(FourByteStruct*)s.get());
}
index++;
}
auto packet = OneGenericStructFourArrayBuilder::Create(std::move(parent_vector));
ASSERT_EQ(one_struct_array.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(one_struct_array.size(), packet_bytes->size());
for (size_t i = 0; i < one_struct_array.size(); i++) {
ASSERT_EQ(one_struct_array[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneGenericStructFourArrayView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto an_array = view.GetAnArray();
ASSERT_EQ(vector_copy.size(), an_array.size());
for (size_t i = 0; i < vector_copy.size(); i++) {
ASSERT_NE(nullptr, an_array[i]);
ASSERT_EQ(vector_copy[i]->struct_type_, an_array[i]->struct_type_);
if (vector_copy[i]->struct_type_ == StructType::FOUR_BYTE) {
ASSERT_EQ(FourByteStruct::Specialize(vector_copy[i].get())->four_bytes_,
FourByteStruct::Specialize(an_array[i].get())->four_bytes_);
} else {
ASSERT_EQ(TwoByteStruct::Specialize(vector_copy[i].get())->two_bytes_,
TwoByteStruct::Specialize(an_array[i].get())->two_bytes_);
}
}
}
vector<uint8_t> one_struct_array_after_fixed{
0x01, 0x02, // two_bytes = 0x0201
0x04, // struct_type_ = FourByte
0xa1, 0xa2, 0xa3, 0xa4, // four_bytes_
0x04, // struct_type_ = FourByte
0xb2, 0xb2, 0xb3, 0xb4, // four_bytes_
0x02, // struct_type_ = TwoByte
0xc3, 0xc2, // two_bytes_
0x04, // struct_type_ = TwoByte
0xd4, 0xd2, 0xd3, 0xd4, // four_bytes_
};
DEFINE_AND_INSTANTIATE_OneGenericStructArrayAfterFixedReflectionTest(one_struct_array_after_fixed);
vector<uint8_t> one_length_type_value_struct{
// _size_(value):16 type value
0x04, 0x00, 0x01, 'o', 'n', 'e', // ONE
0x04, 0x00, 0x02, 't', 'w', 'o', // TWO
0x06, 0x00, 0x03, 't', 'h', 'r', 'e', 'e', // THREE
};
DEFINE_AND_INSTANTIATE_OneLengthTypeValueStructReflectionTest(one_length_type_value_struct);
TEST(GeneratedPacketTest, testOneLengthTypeValueStruct) {
std::shared_ptr<std::vector<uint8_t>> packet_bytes =
std::make_shared<std::vector<uint8_t>>(one_length_type_value_struct);
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneLengthTypeValueStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
auto one = view.GetOneArray();
size_t entry_id = 0;
for (const auto& entry : one) {
switch (entry_id++) {
case 0:
ASSERT_EQ(entry.type_, DataType::ONE);
ASSERT_EQ(entry.value_, std::vector<uint8_t>({'o', 'n', 'e'}));
break;
case 1:
ASSERT_EQ(entry.type_, DataType::TWO);
ASSERT_EQ(entry.value_, std::vector<uint8_t>({'t', 'w', 'o'}));
break;
case 2:
ASSERT_EQ(entry.type_, DataType::THREE);
ASSERT_EQ(entry.value_, std::vector<uint8_t>({'t', 'h', 'r', 'e', 'e'}));
break;
default:
ASSERT_EQ(entry.type_, DataType::UNUSED);
}
}
}
vector<uint8_t> one_length_type_value_struct_padded_10{
0x20, // _size_(payload),
0x14, // valid bytes
0x04, 0x00, 0x01, 'o', 'n', 'e', // ONE
0x04, 0x00, 0x02, 't', 'w', 'o', // TWO
0x06, 0x00, 0x03, 't', 'h', 'r', 'e', 'e', // THREE
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // padding to 30
0x20, // after padding
};
vector<uint8_t> one_length_type_value_struct_padded_18{
0x20, // _size_(payload),
0x0C, // valid bytes
0x04, 0x00, 0x01, 'o', 'n', 'e', // ONE
0x04, 0x00, 0x02, 't', 'w', 'o', // TWO
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // padding to 20
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // padding to 30
0x20, // after padding
};
// TODO: Revisit LTV parsing. Right now, the padding bytes are parsed
// DEFINE_AND_INSTANTIATE_OneLengthTypeValueStructPaddedReflectionTest(one_length_type_value_struct_padded_10,
// one_length_type_value_struct_padded_18);
TEST(GeneratedPacketTest, testOneLengthTypeValueStructPaddedGeneration) {
std::vector<LengthTypeValueStruct> ltv_vector;
LengthTypeValueStruct ltv;
ltv.type_ = DataType::ONE;
ltv.value_ = {
'o',
'n',
'e',
};
ltv_vector.push_back(ltv);
ltv.type_ = DataType::TWO;
ltv.value_ = {
't',
'w',
'o',
};
ltv_vector.push_back(ltv);
uint8_t after_padding = 0x20;
auto packet = OneLengthTypeValueStructPaddedBuilder::Create(12, ltv_vector, after_padding);
ASSERT_EQ(one_length_type_value_struct_padded_18.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(one_length_type_value_struct_padded_18.size(), packet_bytes->size());
for (size_t i = 0; i < one_length_type_value_struct_padded_18.size(); i++) {
ASSERT_EQ(one_length_type_value_struct_padded_18[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneLengthTypeValueStructPaddedView::Create(SizedParentView::Create(packet_bytes_view));
ASSERT_TRUE(view.IsValid());
auto an_array = view.GetOneArray();
// TODO: Revisit LTV parsing. Right now, the padding bytes are parsed
ASSERT_LE(ltv_vector.size(), an_array.size());
for (size_t i = 0; i < ltv_vector.size(); i++) {
ASSERT_EQ(ltv_vector[i].type_, an_array[i].type_);
ASSERT_EQ(ltv_vector[i].value_, an_array[i].value_);
}
ASSERT_EQ(after_padding, view.GetAfterPadding());
}
vector<uint8_t> byte_sized{
0x11, // 1
0x21, 0x22, // 2
0x31, 0x32, 0x33, // 3
0x41, 0x42, 0x43, 0x44, // 4
0x51, 0x52, 0x53, 0x54, 0x55, // 5
0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 6
0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // 7
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, // 8
};
TEST(GeneratedPacketTest, testByteSizedFields) {
uint64_t array[9]{
0xbadbadbad,
0x11, // 1
0x2221, // 2
0x333231, // 3
0x44434241, // 4
0x5554535251, // 5
0x666564636261, // 6
0x77767574737271, // 7
0x8887868584838281, // 8
};
auto packet =
ByteSizedFieldsBuilder::Create(array[1], array[2], array[3], array[4], array[5], array[6], array[7], array[8]);
ASSERT_EQ(byte_sized.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(byte_sized.size(), packet_bytes->size());
for (size_t i = 0; i < byte_sized.size(); i++) {
ASSERT_EQ(byte_sized[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = ByteSizedFieldsView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
ASSERT_EQ(array[1], view.GetOne());
ASSERT_EQ(array[2], view.GetTwo());
ASSERT_EQ(array[3], view.GetThree());
ASSERT_EQ(array[4], view.GetFour());
ASSERT_EQ(array[5], view.GetFive());
ASSERT_EQ(array[6], view.GetSix());
ASSERT_EQ(array[7], view.GetSeven());
ASSERT_EQ(array[8], view.GetEight());
}
DEFINE_AND_INSTANTIATE_ByteSizedFieldsReflectionTest(byte_sized);
TEST(GeneratedPacketTest, testOneGenericStructArrayNoZeroEmpty) {
auto too_few_bytes = std::make_shared<std::vector<uint8_t>>(0);
auto view = OneGenericStructArrayNoZeroView::Create(PacketView<kLittleEndian>(too_few_bytes));
for (size_t i = 0; i < 10; i++) {
if (view.IsValid()) {
view.GetAnArray().size();
}
too_few_bytes->push_back(0);
view = OneGenericStructArrayNoZeroView::Create(PacketView<kLittleEndian>(too_few_bytes));
}
std::vector<uint8_t> a_two_byte_struct = {
static_cast<uint8_t>(StructTypeNoZero::TWO_BYTE),
0x01,
0x02,
};
too_few_bytes = std::make_shared<std::vector<uint8_t>>(a_two_byte_struct);
view = OneGenericStructArrayNoZeroView::Create(PacketView<kLittleEndian>(too_few_bytes));
ASSERT_TRUE(view.IsValid());
ASSERT_EQ(1, view.GetAnArray().size());
}
TEST(GeneratedPacketTest, testToStringOutput) {
std::vector<TwoRelatedNumbersBe> count_array;
for (uint8_t i = 1; i < 5; i++) {
TwoRelatedNumbersBe trn;
trn.id_ = i;
trn.count_ = 0x0102 * i;
count_array.push_back(trn);
}
auto packet = ArrayOfStructBeBuilder::Create(count_array);
ASSERT_EQ(array_of_struct_be.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(array_of_struct_be.size(), packet_bytes->size());
for (size_t i = 0; i < array_of_struct_be.size(); i++) {
ASSERT_EQ(array_of_struct_be[i], packet_bytes->at(i));
}
PacketView<!kLittleEndian> packet_bytes_view(packet_bytes);
auto view = ArrayOfStructBeView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
ASSERT_EQ(
"ArrayOfStructBe { array_count = 0x4, array = VECTOR[TwoRelatedNumbersBe { id = 0x1, count = 0x102 }, "
"TwoRelatedNumbersBe { id = 0x2, count = 0x204 }, TwoRelatedNumbersBe { id = 0x3, count = 0x306 }, "
"TwoRelatedNumbersBe { id = 0x4, count = 0x408 }] }",
view.ToString());
}
TEST(GeneratedPacketTest, testToStringOneFixedTypesStruct) {
StructWithFixedTypes swf;
swf.four_bits_ = FourBits::FIVE;
swf.id_ = 0x0d;
swf.array_ = {{0x01, 0x02, 0x03}};
swf.six_bytes_ = SixBytes{{0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6}};
auto packet = OneFixedTypesStructBuilder::Create(swf);
ASSERT_EQ(one_fixed_types_struct.size(), packet->size());
std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
BitInserter it(*packet_bytes);
packet->Serialize(it);
ASSERT_EQ(one_fixed_types_struct.size(), packet_bytes->size());
for (size_t i = 0; i < one_fixed_types_struct.size(); i++) {
ASSERT_EQ(one_fixed_types_struct[i], packet_bytes->at(i));
}
PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
auto view = OneFixedTypesStructView::Create(packet_bytes_view);
ASSERT_TRUE(view.IsValid());
ASSERT_EQ(
"OneFixedTypesStruct { one = StructWithFixedTypes { four_bits = FIVE, id = 0xd, array = ARRAY[0x1, 0x2, 0x3], "
"example_checksum = CHECKSUM, six_bytes = SixBytes } }",
view.ToString());
}
} // namespace parser
} // namespace packet
} // namespace bluetooth