/* * 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 #include #include #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 child_two_two_three = { 0x20 /* Reserved : 4, FourBits::TWO */, 0x03 /* FourBits::THREE, Reserved : 4 */, }; vector child = { 0x12 /* fixed */, 0x02 /* Size of the payload */, 0xa1 /* First byte of the payload */, 0xa2, 0xb1 /* footer */, }; vector 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> packet_bytes = std::make_shared>(); 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 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> packet_bytes = std::make_shared>(); 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 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 too_small_bytes = {0x34}; auto too_small = std::make_shared>(too_small_bytes.begin(), too_small_bytes.end()); ParentWithSixBytesView invalid_parent = ParentWithSixBytesView::Create(PacketView(too_small)); ASSERT_FALSE(invalid_parent.IsValid()); ChildWithSixBytesView invalid = ChildWithSixBytesView::Create(ParentWithSixBytesView::Create(PacketView(too_small))); ASSERT_FALSE(invalid.IsValid()); } TEST(GeneratedPacketTest, testValidateTooSmall) { std::vector too_small_bytes = {0x34, 0x12, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11}; auto too_small = std::make_shared>(too_small_bytes.begin(), too_small_bytes.end()); ParentWithSixBytesView valid_parent = ParentWithSixBytesView::Create(PacketView(too_small)); ASSERT_TRUE(valid_parent.IsValid()); ChildWithSixBytesView invalid = ChildWithSixBytesView::Create(ParentWithSixBytesView::Create(PacketView(too_small))); ASSERT_FALSE(invalid.IsValid()); } TEST(GeneratedPacketTest, testValidateJustRight) { std::vector just_right_bytes = {0x34, 0x12, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; auto just_right = std::make_shared>(just_right_bytes.begin(), just_right_bytes.end()); ChildWithSixBytesView valid = ChildWithSixBytesView::Create(ParentWithSixBytesView::Create(PacketView(just_right))); ASSERT_TRUE(valid.IsValid()); } TEST(GeneratedPacketTest, testValidateTooBig) { std::vector too_big_bytes = {0x34, 0x12, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x20}; auto too_big = std::make_shared>(too_big_bytes.begin(), too_big_bytes.end()); ChildWithSixBytesView lenient = ChildWithSixBytesView::Create(ParentWithSixBytesView::Create(PacketView(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> packet_bytes = std::make_shared>(); 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 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> packet_bytes = std::make_shared>(); 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 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 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> packet_bytes = std::make_shared>(); 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 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> packet_bytes = std::make_shared>(); 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 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 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()); ASSERT_EQ(parent_with_sum.size(), packet->size()); std::shared_ptr> packet_bytes = std::make_shared>(); 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 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 corrupted_bytes_view(packet_bytes); ParentWithSumView corrupted_view = ParentWithSumView::Create(corrupted_bytes_view); ASSERT_FALSE(corrupted_view.IsValid()); } namespace { vector 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> packet_bytes = std::make_shared>(); 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 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 parent_size_modifier = { 0x02 /* Size */, 0x11 /* TwoBytes */, 0x12, }; } // namespace TEST(GeneratedPacketTest, testParentSizeModifier) { uint16_t two_bytes = 0x1211; auto packet = ParentSizeModifierBuilder::Create(std::make_unique(), two_bytes); ASSERT_EQ(parent_size_modifier.size(), packet->size()); std::shared_ptr> packet_bytes = std::make_shared>(); 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 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 copy_array(fixed_array); fixed_array[1] = ForArrays::ONE; std::shared_ptr> packet_bytes = std::make_shared>(); 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 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 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 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 copy_array(sized_array); sized_array[1] = ForArrays::ONE; std::shared_ptr> packet_bytes = std::make_shared>(); 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 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 count_array_enum{ 0x03, // _count_ 0x01, // ONE 0x00, 0x02, // TWO_THREE 0x03, 0xff, // FFFF 0xff, }; } TEST(GeneratedPacketTest, testCountArrayEnum) { std::vector 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> packet_bytes = std::make_shared>(); 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 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 byte_array; for (uint8_t i = 0; i < byte_array_size; i++) byte_array[i] = i; constexpr int word_array_size = 8; std::array 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> packet_bytes = std::make_shared>(); 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 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 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> packet_bytes = std::make_shared>(); 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 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 fou_variable{ 0x04, 'f', 'o', 'u', // too short }; TEST(GeneratedPacketTest, testOneVariableFieldTooShort) { std::shared_ptr> packet_bytes = std::make_shared>(fou_variable); PacketView 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 sized_array; sized_array.emplace_back("one"); sized_array.emplace_back("two"); std::shared_ptr> packet_bytes = std::make_shared>(sized_array_variable_too_short); PacketView 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 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 sized_array; sized_array.emplace_back("on"); std::shared_ptr> packet_bytes = std::make_shared>(sized_array_variable_first_too_short); PacketView 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 fixed_array{std::string("one"), std::string("two"), std::string("three"), std::string("four")}; std::shared_ptr> packet_bytes = std::make_shared>(fixed_array_variable_too_short); PacketView 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 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> packet_bytes = std::make_shared>(count_array_variable_extra); PacketView 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 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 count_array; count_array.emplace_back("one"); count_array.emplace_back("two"); count_array.emplace_back("three"); std::shared_ptr> packet_bytes = std::make_shared>(count_array_variable_too_few); PacketView 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 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> packet_bytes = std::make_shared>(); 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 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 two_structs{ 0x01, 0x01, 0x02, // id, id * 0x0201 0x02, 0x02, 0x04, }; TEST(GeneratedPacketTest, testTwoStructs) { std::vector 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> packet_bytes = std::make_shared>(); 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 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 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 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> packet_bytes = std::make_shared>(); 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 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> packet_bytes = std::make_shared>(); 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 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> packet_bytes = std::make_shared>(array_of_struct_and_another); PacketView 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 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 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> packet_bytes = std::make_shared>(); 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 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> packet_bytes = std::make_shared>(); 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 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 packet_bytes_view(std::make_shared>(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> packet_bytes = std::make_shared>(); BitInserter it(*packet_bytes); packet->Serialize(it); ASSERT_EQ(*packet_bytes, bit_field_array_packet); } std::vector child_two_two_two_ = {0x20, 0x02}; std::vector child_two_two_three_ = {0x20, 0x03}; std::vector 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 one_versionless_struct_packet = {0x01}; std::vector one_versioned_struct_packet = {0x02, 0x03 /* version */, 0x04, 0x05, 0x06}; std::vector one_version_one_struct_packet = {0x03, 0x01 /* version */, 0x02}; std::vector 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 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> packet_bytes = std::make_shared>(); 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 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 two_structs_be{ 0x01, 0x01, 0x02, // id, id * 0x0102 0x02, 0x02, 0x04, }; TEST(GeneratedPacketTest, testTwoStructsBe) { std::vector 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> packet_bytes = std::make_shared>(); 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 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 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 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> packet_bytes = std::make_shared>(); 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 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 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> packet_bytes = std::make_shared>(); 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 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 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 two_byte_struct_ptr = std::make_unique(two_byte_struct); auto packet = OneGenericStructBuilder::Create(std::move(two_byte_struct_ptr)); ASSERT_EQ(generic_struct_two.size(), packet->size()); std::shared_ptr> packet_bytes = std::make_shared>(); 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 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(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 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 four_byte_struct_p = std::make_unique(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> packet_bytes = std::make_shared>(); 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 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 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> parent_vector; std::unique_ptr fbs; std::unique_ptr tbs; fbs = std::make_unique(); fbs->four_bytes_ = 0xa4a3a2a1; parent_vector.push_back(std::move(fbs)); fbs = std::make_unique(); fbs->four_bytes_ = 0xb4b3b2b2; parent_vector.push_back(std::move(fbs)); tbs = std::make_unique(); tbs->two_bytes_ = 0xc2c3; parent_vector.push_back(std::move(tbs)); fbs = std::make_unique(); fbs->four_bytes_ = 0xd4d3d2d4; parent_vector.push_back(std::move(fbs)); std::vector> vector_copy; for (auto& s : parent_vector) { if (s->struct_type_ == StructType::TWO_BYTE) { vector_copy.push_back(std::make_unique(*(TwoByteStruct*)s.get())); } if (s->struct_type_ == StructType::FOUR_BYTE) { vector_copy.push_back(std::make_unique(*(FourByteStruct*)s.get())); } } auto packet = OneGenericStructArrayBuilder::Create(std::move(parent_vector)); ASSERT_EQ(one_struct_array.size(), packet->size()); std::shared_ptr> packet_bytes = std::make_shared>(); 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 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, 4> parent_vector; std::unique_ptr fbs; std::unique_ptr tbs; fbs = std::make_unique(); fbs->four_bytes_ = 0xa4a3a2a1; parent_vector[0] = std::move(fbs); fbs = std::make_unique(); fbs->four_bytes_ = 0xb4b3b2b2; parent_vector[1] = std::move(fbs); tbs = std::make_unique(); tbs->two_bytes_ = 0xc2c3; parent_vector[2] = std::move(tbs); fbs = std::make_unique(); fbs->four_bytes_ = 0xd4d3d2d4; parent_vector[3] = std::move(fbs); std::array, 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*)s.get()); } if (s->struct_type_ == StructType::FOUR_BYTE) { vector_copy[index] = std::make_unique(*(FourByteStruct*)s.get()); } index++; } auto packet = OneGenericStructFourArrayBuilder::Create(std::move(parent_vector)); ASSERT_EQ(one_struct_array.size(), packet->size()); std::shared_ptr> packet_bytes = std::make_shared>(); 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 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 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 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> packet_bytes = std::make_shared>(one_length_type_value_struct); PacketView 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({'o', 'n', 'e'})); break; case 1: ASSERT_EQ(entry.type_, DataType::TWO); ASSERT_EQ(entry.value_, std::vector({'t', 'w', 'o'})); break; case 2: ASSERT_EQ(entry.type_, DataType::THREE); ASSERT_EQ(entry.value_, std::vector({'t', 'h', 'r', 'e', 'e'})); break; default: ASSERT_EQ(entry.type_, DataType::UNUSED); } } } vector 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 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 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> packet_bytes = std::make_shared>(); 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 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 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> packet_bytes = std::make_shared>(); 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 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>(0); auto view = OneGenericStructArrayNoZeroView::Create(PacketView(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(too_few_bytes)); } std::vector a_two_byte_struct = { static_cast(StructTypeNoZero::TWO_BYTE), 0x01, 0x02, }; too_few_bytes = std::make_shared>(a_two_byte_struct); view = OneGenericStructArrayNoZeroView::Create(PacketView(too_few_bytes)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(1, view.GetAnArray().size()); } TEST(GeneratedPacketTest, testToStringOutput) { std::vector 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> packet_bytes = std::make_shared>(); 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 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> packet_bytes = std::make_shared>(); 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 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