// Copyright 2021 The Pigweed Authors // // 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 // // https://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. #include "pw_bluetooth_hci/packet.h" #include "gtest/gtest.h" #include "pw_bytes/array.h" #include "pw_bytes/byte_builder.h" #include "pw_status/status.h" namespace pw::bluetooth_hci { namespace { class PacketTest : public ::testing::Test { protected: constexpr static size_t kMaxHeaderSizeBytes = std::max({ CommandPacket::kHeaderSizeBytes, AsyncDataPacket::kHeaderSizeBytes, SyncDataPacket::kHeaderSizeBytes, EventPacket::kHeaderSizeBytes, }); // Arbitrarily add at most 2 bytes worth of payload (data or parameters). constexpr static size_t kArbitraryMaxPayloadSizeBytes = 2; constexpr static size_t kMaxPacketSizeBytes = kMaxHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes; std::array packet_buffer_; }; TEST_F(PacketTest, CommandPacketHeaderUndersizedEncode) { const CommandPacket packet(0u, ConstByteSpan()); EXPECT_EQ(0u, packet.parameters().size_bytes()); const Result encode_result = packet.Encode( {packet_buffer_.data(), CommandPacket::kHeaderSizeBytes - 1}); EXPECT_EQ(Status::ResourceExhausted(), encode_result.status()); } TEST_F(PacketTest, CommandPacketHeaderUndersizedDecode) { EXPECT_FALSE(CommandPacket::Decode( {packet_buffer_.data(), CommandPacket::kHeaderSizeBytes - 1}) .has_value()); } TEST_F(PacketTest, CommandPacketHeaderOnlyEncodeAndDecode) { constexpr uint16_t kOpcodeCommandField = 0b00'0000'0000; constexpr uint8_t kOpcodeGroupField = 0b11'1111; constexpr uint16_t kOpcode = (kOpcodeGroupField << 10) | kOpcodeCommandField; const CommandPacket packet(kOpcode, ConstByteSpan()); EXPECT_EQ(packet.type(), Packet::Type::kCommandPacket); EXPECT_EQ(packet.size_bytes(), CommandPacket::kHeaderSizeBytes); EXPECT_EQ(packet.opcode(), kOpcode); EXPECT_EQ(packet.opcode_command_field(), kOpcodeCommandField); EXPECT_EQ(packet.opcode_group_field(), kOpcodeGroupField); EXPECT_EQ(packet.parameters().size_bytes(), 0u); const Result encode_result = packet.Encode(packet_buffer_); ASSERT_EQ(OkStatus(), encode_result.status()); constexpr std::array kExpectedEncodedPacket = bytes::MakeArray( 0b0000'0000, 0b1111'1100, 0b0000'0000); const ConstByteSpan& encoded_packet = encode_result.value(); EXPECT_TRUE(std::equal(kExpectedEncodedPacket.begin(), kExpectedEncodedPacket.end(), encoded_packet.begin(), encoded_packet.end())); // First, decode it from a perfectly sized span which we just encoded. std::optional possible_packet = CommandPacket::Decode(encoded_packet); ASSERT_TRUE(possible_packet.has_value()); CommandPacket& decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kCommandPacket); EXPECT_EQ(decoded_packet.size_bytes(), CommandPacket::kHeaderSizeBytes); EXPECT_EQ(decoded_packet.opcode(), kOpcode); EXPECT_EQ(decoded_packet.opcode_command_field(), kOpcodeCommandField); EXPECT_EQ(decoded_packet.opcode_group_field(), kOpcodeGroupField); EXPECT_EQ(decoded_packet.parameters().size_bytes(), 0u); // Second, decode it from an oversized buffer. possible_packet = CommandPacket::Decode({packet_buffer_}); ASSERT_TRUE(possible_packet.has_value()); decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kCommandPacket); EXPECT_EQ(decoded_packet.size_bytes(), CommandPacket::kHeaderSizeBytes); EXPECT_EQ(decoded_packet.opcode(), kOpcode); EXPECT_EQ(decoded_packet.opcode_command_field(), kOpcodeCommandField); EXPECT_EQ(decoded_packet.opcode_group_field(), kOpcodeGroupField); EXPECT_EQ(decoded_packet.parameters().size_bytes(), 0u); } TEST_F(PacketTest, CommandPacketWithParametersEncodeAndDecode) { constexpr uint16_t kOpcodeCommandField = 0b10'1010'1010; constexpr uint8_t kOpcodeGroupField = 0b10'1010; constexpr uint16_t kOpcode = (kOpcodeGroupField << 10) | kOpcodeCommandField; constexpr std::array kParameters = bytes::MakeArray(1, 2); const CommandPacket packet(kOpcode, kParameters); EXPECT_EQ(packet.type(), Packet::Type::kCommandPacket); EXPECT_EQ(packet.size_bytes(), CommandPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(packet.opcode(), kOpcode); EXPECT_EQ(packet.opcode_command_field(), kOpcodeCommandField); EXPECT_EQ(packet.opcode_group_field(), kOpcodeGroupField); EXPECT_EQ(packet.parameters().size_bytes(), kArbitraryMaxPayloadSizeBytes); const Result encode_result = packet.Encode(packet_buffer_); ASSERT_EQ(OkStatus(), encode_result.status()); constexpr std::array kExpectedEncodedPacket = bytes::MakeArray( 0b1010'1010, 0b1010'1010, 0b0000'0010, 1, 2); const ConstByteSpan& encoded_packet = encode_result.value(); EXPECT_TRUE(std::equal(kExpectedEncodedPacket.begin(), kExpectedEncodedPacket.end(), encoded_packet.begin(), encoded_packet.end())); // First, decode it from a perfectly sized span which we just encoded. std::optional possible_packet = CommandPacket::Decode(encoded_packet); ASSERT_TRUE(possible_packet.has_value()); CommandPacket& decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kCommandPacket); EXPECT_EQ(decoded_packet.size_bytes(), CommandPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(decoded_packet.opcode(), kOpcode); EXPECT_EQ(decoded_packet.opcode_command_field(), kOpcodeCommandField); EXPECT_EQ(decoded_packet.opcode_group_field(), kOpcodeGroupField); EXPECT_EQ(decoded_packet.parameters().size_bytes(), kArbitraryMaxPayloadSizeBytes); // Second, decode it from an oversized buffer. possible_packet = CommandPacket::Decode({packet_buffer_}); ASSERT_TRUE(possible_packet.has_value()); decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kCommandPacket); EXPECT_EQ(decoded_packet.size_bytes(), CommandPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(decoded_packet.opcode(), kOpcode); EXPECT_EQ(decoded_packet.opcode_command_field(), kOpcodeCommandField); EXPECT_EQ(decoded_packet.opcode_group_field(), kOpcodeGroupField); EXPECT_EQ(decoded_packet.parameters().size_bytes(), kArbitraryMaxPayloadSizeBytes); } TEST_F(PacketTest, AsyncDataPacketHeaderUndersizedEncode) { const AsyncDataPacket packet(0u, ConstByteSpan()); EXPECT_EQ(0u, packet.data().size_bytes()); const Result encode_result = packet.Encode( {packet_buffer_.data(), AsyncDataPacket::kHeaderSizeBytes - 1}); EXPECT_EQ(Status::ResourceExhausted(), encode_result.status()); } TEST_F(PacketTest, AsyncDataPacketHeaderUndersizedDecode) { EXPECT_FALSE(AsyncDataPacket::Decode({packet_buffer_.data(), AsyncDataPacket::kHeaderSizeBytes - 1}) .has_value()); } TEST_F(PacketTest, AsyncDataPacketHeaderOnlyEncodeAndDecode) { constexpr uint16_t kHandle = 0b00'0000'0000; constexpr uint8_t kPbFlag = 0b01; constexpr uint8_t kBcFlag = 0b10; constexpr uint16_t kHandleAndFragmentationBits = kHandle | (kPbFlag << 12) | (kBcFlag << 14); const AsyncDataPacket packet(kHandleAndFragmentationBits, ConstByteSpan()); EXPECT_EQ(packet.type(), Packet::Type::kAsyncDataPacket); EXPECT_EQ(packet.size_bytes(), AsyncDataPacket::kHeaderSizeBytes); EXPECT_EQ(packet.handle_and_fragmentation_bits(), kHandleAndFragmentationBits); EXPECT_EQ(packet.handle(), kHandle); EXPECT_EQ(packet.pb_flag(), kPbFlag); EXPECT_EQ(packet.bc_flag(), kBcFlag); EXPECT_EQ(packet.data().size_bytes(), 0u); const Result encode_result = packet.Encode(packet_buffer_); ASSERT_EQ(OkStatus(), encode_result.status()); constexpr std::array kExpectedEncodedPacket = bytes::MakeArray( 0b0000'0000, 0b1001'0000, 0b0000'0000, 0b0000'0000); const ConstByteSpan& encoded_packet = encode_result.value(); EXPECT_TRUE(std::equal(kExpectedEncodedPacket.begin(), kExpectedEncodedPacket.end(), encoded_packet.begin(), encoded_packet.end())); // First, decode it from a perfectly sized span which we just encoded. std::optional possible_packet = AsyncDataPacket::Decode(encoded_packet); ASSERT_TRUE(possible_packet.has_value()); AsyncDataPacket& decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kAsyncDataPacket); EXPECT_EQ(decoded_packet.size_bytes(), AsyncDataPacket::kHeaderSizeBytes); EXPECT_EQ(decoded_packet.handle_and_fragmentation_bits(), kHandleAndFragmentationBits); EXPECT_EQ(decoded_packet.handle(), kHandle); EXPECT_EQ(decoded_packet.pb_flag(), kPbFlag); EXPECT_EQ(decoded_packet.bc_flag(), kBcFlag); EXPECT_EQ(decoded_packet.data().size_bytes(), 0u); // Second, decode it from an oversized buffer. possible_packet = AsyncDataPacket::Decode({packet_buffer_}); ASSERT_TRUE(possible_packet.has_value()); decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kAsyncDataPacket); EXPECT_EQ(decoded_packet.size_bytes(), AsyncDataPacket::kHeaderSizeBytes); EXPECT_EQ(decoded_packet.handle_and_fragmentation_bits(), kHandleAndFragmentationBits); EXPECT_EQ(decoded_packet.handle(), kHandle); EXPECT_EQ(decoded_packet.pb_flag(), kPbFlag); EXPECT_EQ(decoded_packet.bc_flag(), kBcFlag); EXPECT_EQ(decoded_packet.data().size_bytes(), 0u); } TEST_F(PacketTest, AsyncDataPacketWithDataEncodeAndDecode) { constexpr uint16_t kHandle = 0b00'0000'0000; constexpr uint8_t kPbFlag = 0b01; constexpr uint8_t kBcFlag = 0b10; constexpr uint16_t kHandleAndFragmentationBits = kHandle | (kPbFlag << 12) | (kBcFlag << 14); constexpr std::array kData = bytes::MakeArray(1, 2); const AsyncDataPacket packet(kHandleAndFragmentationBits, kData); EXPECT_EQ(packet.type(), Packet::Type::kAsyncDataPacket); EXPECT_EQ(packet.size_bytes(), AsyncDataPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(packet.handle_and_fragmentation_bits(), kHandleAndFragmentationBits); EXPECT_EQ(packet.handle(), kHandle); EXPECT_EQ(packet.pb_flag(), kPbFlag); EXPECT_EQ(packet.bc_flag(), kBcFlag); EXPECT_EQ(packet.data().size_bytes(), kArbitraryMaxPayloadSizeBytes); const Result encode_result = packet.Encode(packet_buffer_); ASSERT_EQ(OkStatus(), encode_result.status()); constexpr std::array kExpectedEncodedPacket = bytes::MakeArray( 0b0000'0000, 0b1001'0000, 0b0000'0010, 0b0000'0000, 1, 2); const ConstByteSpan& encoded_packet = encode_result.value(); EXPECT_TRUE(std::equal(kExpectedEncodedPacket.begin(), kExpectedEncodedPacket.end(), encoded_packet.begin(), encoded_packet.end())); // First, decode it from a perfectly sized span which we just encoded. std::optional possible_packet = AsyncDataPacket::Decode(encoded_packet); ASSERT_TRUE(possible_packet.has_value()); AsyncDataPacket& decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kAsyncDataPacket); EXPECT_EQ(decoded_packet.size_bytes(), AsyncDataPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(decoded_packet.handle_and_fragmentation_bits(), kHandleAndFragmentationBits); EXPECT_EQ(decoded_packet.handle(), kHandle); EXPECT_EQ(decoded_packet.pb_flag(), kPbFlag); EXPECT_EQ(decoded_packet.bc_flag(), kBcFlag); EXPECT_EQ(decoded_packet.data().size_bytes(), kArbitraryMaxPayloadSizeBytes); // Second, decode it from an oversized buffer. possible_packet = AsyncDataPacket::Decode({packet_buffer_}); ASSERT_TRUE(possible_packet.has_value()); decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kAsyncDataPacket); EXPECT_EQ(decoded_packet.size_bytes(), AsyncDataPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(decoded_packet.handle_and_fragmentation_bits(), kHandleAndFragmentationBits); EXPECT_EQ(decoded_packet.handle(), kHandle); EXPECT_EQ(decoded_packet.pb_flag(), kPbFlag); EXPECT_EQ(decoded_packet.bc_flag(), kBcFlag); EXPECT_EQ(decoded_packet.data().size_bytes(), kArbitraryMaxPayloadSizeBytes); } TEST_F(PacketTest, SyncDataPacketHeaderUndersizedEncode) { const SyncDataPacket packet(0u, ConstByteSpan()); EXPECT_EQ(0u, packet.data().size_bytes()); const Result encode_result = packet.Encode( {packet_buffer_.data(), SyncDataPacket::kHeaderSizeBytes - 1}); EXPECT_EQ(Status::ResourceExhausted(), encode_result.status()); } TEST_F(PacketTest, SyncDataPacketHeaderUndersizedDecode) { EXPECT_FALSE(SyncDataPacket::Decode({packet_buffer_.data(), SyncDataPacket::kHeaderSizeBytes - 1}) .has_value()); } TEST_F(PacketTest, SyncDataPacketHeaderOnlyEncodeAndDecode) { constexpr uint16_t kHandle = 0b00'0000'0000; constexpr uint8_t kPacketStatusFlag = 0b11; constexpr uint8_t kReservedBits = 0; constexpr uint16_t kHandleAndStatusBits = kHandle | (kPacketStatusFlag << 12) | (kReservedBits << 14); const SyncDataPacket packet(kHandleAndStatusBits, ConstByteSpan()); EXPECT_EQ(packet.type(), Packet::Type::kSyncDataPacket); EXPECT_EQ(packet.size_bytes(), SyncDataPacket::kHeaderSizeBytes); EXPECT_EQ(packet.handle_and_status_bits(), kHandleAndStatusBits); EXPECT_EQ(packet.handle(), kHandle); EXPECT_EQ(packet.packet_status_flag(), kPacketStatusFlag); EXPECT_EQ(packet.data().size_bytes(), 0u); const Result encode_result = packet.Encode(packet_buffer_); ASSERT_EQ(OkStatus(), encode_result.status()); constexpr std::array kExpectedEncodedPacket = bytes::MakeArray( 0b0000'0000, 0b0011'0000, 0b0000'0000); const ConstByteSpan& encoded_packet = encode_result.value(); EXPECT_TRUE(std::equal(kExpectedEncodedPacket.begin(), kExpectedEncodedPacket.end(), encoded_packet.begin(), encoded_packet.end())); // First, decode it from a perfectly sized span which we just encoded. std::optional possible_packet = SyncDataPacket::Decode(encoded_packet); ASSERT_TRUE(possible_packet.has_value()); SyncDataPacket& decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kSyncDataPacket); EXPECT_EQ(decoded_packet.size_bytes(), SyncDataPacket::kHeaderSizeBytes); EXPECT_EQ(packet.handle_and_status_bits(), kHandleAndStatusBits); EXPECT_EQ(decoded_packet.packet_status_flag(), kPacketStatusFlag); EXPECT_EQ(decoded_packet.handle(), kHandle); EXPECT_EQ(decoded_packet.data().size_bytes(), 0u); // Second, decode it from an oversized buffer. possible_packet = SyncDataPacket::Decode({packet_buffer_}); ASSERT_TRUE(possible_packet.has_value()); decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kSyncDataPacket); EXPECT_EQ(decoded_packet.size_bytes(), SyncDataPacket::kHeaderSizeBytes); EXPECT_EQ(packet.handle_and_status_bits(), kHandleAndStatusBits); EXPECT_EQ(decoded_packet.handle(), kHandle); EXPECT_EQ(decoded_packet.packet_status_flag(), kPacketStatusFlag); EXPECT_EQ(decoded_packet.data().size_bytes(), 0u); } TEST_F(PacketTest, SyncDataPacketWithDataEncodeAndDecode) { constexpr uint16_t kHandle = 0b00'0000'0000; constexpr uint8_t kPacketStatusFlag = 0b11; constexpr uint8_t kReservedBits = 0; constexpr uint16_t kHandleAndStatusBits = kHandle | (kPacketStatusFlag << 12) | (kReservedBits << 14); constexpr std::array kData = bytes::MakeArray(1, 2); const SyncDataPacket packet(kHandleAndStatusBits, kData); EXPECT_EQ(packet.type(), Packet::Type::kSyncDataPacket); EXPECT_EQ(packet.size_bytes(), SyncDataPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(packet.handle_and_status_bits(), kHandleAndStatusBits); EXPECT_EQ(packet.handle(), kHandle); EXPECT_EQ(packet.packet_status_flag(), kPacketStatusFlag); EXPECT_EQ(packet.data().size_bytes(), kArbitraryMaxPayloadSizeBytes); const Result encode_result = packet.Encode(packet_buffer_); ASSERT_EQ(OkStatus(), encode_result.status()); constexpr std::array kExpectedEncodedPacket = bytes::MakeArray( 0b0000'0000, 0b0011'0000, 0b0000'0010, 1, 2); const ConstByteSpan& encoded_packet = encode_result.value(); EXPECT_TRUE(std::equal(kExpectedEncodedPacket.begin(), kExpectedEncodedPacket.end(), encoded_packet.begin(), encoded_packet.end())); // First, decode it from a perfectly sized span which we just encoded. std::optional possible_packet = SyncDataPacket::Decode(encoded_packet); ASSERT_TRUE(possible_packet.has_value()); SyncDataPacket& decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kSyncDataPacket); EXPECT_EQ(decoded_packet.size_bytes(), SyncDataPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(packet.handle_and_status_bits(), kHandleAndStatusBits); EXPECT_EQ(packet.handle(), kHandle); EXPECT_EQ(packet.packet_status_flag(), kPacketStatusFlag); EXPECT_EQ(decoded_packet.data().size_bytes(), kArbitraryMaxPayloadSizeBytes); // Second, decode it from an oversized buffer. possible_packet = SyncDataPacket::Decode({packet_buffer_}); ASSERT_TRUE(possible_packet.has_value()); decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kSyncDataPacket); EXPECT_EQ(decoded_packet.size_bytes(), SyncDataPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(packet.handle_and_status_bits(), kHandleAndStatusBits); EXPECT_EQ(packet.handle(), kHandle); EXPECT_EQ(packet.packet_status_flag(), kPacketStatusFlag); EXPECT_EQ(decoded_packet.data().size_bytes(), kArbitraryMaxPayloadSizeBytes); } TEST_F(PacketTest, EventPacketHeaderUndersizedEncode) { const EventPacket packet(0u, ConstByteSpan()); EXPECT_EQ(0u, packet.parameters().size_bytes()); const Result encode_result = packet.Encode({packet_buffer_.data(), EventPacket::kHeaderSizeBytes - 1}); EXPECT_EQ(Status::ResourceExhausted(), encode_result.status()); } TEST_F(PacketTest, EventPacketHeaderUndersizedDecode) { EXPECT_FALSE(EventPacket::Decode( {packet_buffer_.data(), EventPacket::kHeaderSizeBytes - 1}) .has_value()); } TEST_F(PacketTest, EventPacketHeaderOnlyEncodeAndDecode) { constexpr uint8_t kEventCode = 0b1111'1111; const EventPacket packet(kEventCode, ConstByteSpan()); EXPECT_EQ(packet.type(), Packet::Type::kEventPacket); EXPECT_EQ(packet.size_bytes(), EventPacket::kHeaderSizeBytes); EXPECT_EQ(packet.event_code(), kEventCode); EXPECT_EQ(packet.parameters().size_bytes(), 0u); const Result encode_result = packet.Encode(packet_buffer_); ASSERT_EQ(OkStatus(), encode_result.status()); constexpr std::array kExpectedEncodedPacket = bytes::MakeArray(0b1111'11111, 0b0000'0000); const ConstByteSpan& encoded_packet = encode_result.value(); EXPECT_TRUE(std::equal(kExpectedEncodedPacket.begin(), kExpectedEncodedPacket.end(), encoded_packet.begin(), encoded_packet.end())); // First, decode it from a perfectly sized span which we just encoded. std::optional possible_packet = EventPacket::Decode(encoded_packet); ASSERT_TRUE(possible_packet.has_value()); EventPacket& decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kEventPacket); EXPECT_EQ(decoded_packet.size_bytes(), EventPacket::kHeaderSizeBytes); EXPECT_EQ(decoded_packet.event_code(), kEventCode); EXPECT_EQ(decoded_packet.parameters().size_bytes(), 0u); // Second, decode it from an oversized buffer. possible_packet = EventPacket::Decode({packet_buffer_}); ASSERT_TRUE(possible_packet.has_value()); decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kEventPacket); EXPECT_EQ(decoded_packet.size_bytes(), EventPacket::kHeaderSizeBytes); EXPECT_EQ(decoded_packet.event_code(), kEventCode); EXPECT_EQ(decoded_packet.parameters().size_bytes(), 0u); } TEST_F(PacketTest, EventPacketWithParametersEncodeAndDecode) { constexpr uint8_t kEventCode = 0b1111'0000; constexpr std::array kParameters = bytes::MakeArray(1, 2); const EventPacket packet(kEventCode, kParameters); EXPECT_EQ(packet.type(), Packet::Type::kEventPacket); EXPECT_EQ(packet.size_bytes(), EventPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(packet.event_code(), kEventCode); EXPECT_EQ(packet.parameters().size_bytes(), kArbitraryMaxPayloadSizeBytes); const Result encode_result = packet.Encode(packet_buffer_); ASSERT_EQ(OkStatus(), encode_result.status()); constexpr std::array kExpectedEncodedPacket = bytes::MakeArray(0b1111'0000, 0b0000'0010, 1, 2); const ConstByteSpan& encoded_packet = encode_result.value(); EXPECT_TRUE(std::equal(kExpectedEncodedPacket.begin(), kExpectedEncodedPacket.end(), encoded_packet.begin(), encoded_packet.end())); // First, decode it from a perfectly sized span which we just encoded. std::optional possible_packet = EventPacket::Decode(encoded_packet); ASSERT_TRUE(possible_packet.has_value()); EventPacket& decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kEventPacket); EXPECT_EQ(decoded_packet.size_bytes(), EventPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(decoded_packet.event_code(), kEventCode); EXPECT_EQ(decoded_packet.parameters().size_bytes(), kArbitraryMaxPayloadSizeBytes); // Second, decode it from an oversized buffer. possible_packet = EventPacket::Decode({packet_buffer_}); ASSERT_TRUE(possible_packet.has_value()); decoded_packet = possible_packet.value(); EXPECT_EQ(decoded_packet.type(), Packet::Type::kEventPacket); EXPECT_EQ(decoded_packet.size_bytes(), EventPacket::kHeaderSizeBytes + kArbitraryMaxPayloadSizeBytes); EXPECT_EQ(decoded_packet.event_code(), kEventCode); EXPECT_EQ(decoded_packet.parameters().size_bytes(), kArbitraryMaxPayloadSizeBytes); } } // namespace } // namespace pw::bluetooth_hci