blob: f5301d5c9c4140e03a46b25a7dec6988070cc4a8 [file] [log] [blame]
// 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<std::byte, kMaxPacketSizeBytes> packet_buffer_;
};
TEST_F(PacketTest, CommandPacketHeaderUndersizedEncode) {
const CommandPacket packet(0u, ConstByteSpan());
EXPECT_EQ(0u, packet.parameters().size_bytes());
const Result<ConstByteSpan> 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<ConstByteSpan> encode_result = packet.Encode(packet_buffer_);
ASSERT_EQ(OkStatus(), encode_result.status());
constexpr std::array<const std::byte, CommandPacket::kHeaderSizeBytes>
kExpectedEncodedPacket = bytes::MakeArray<const std::byte>(
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<CommandPacket> 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<const std::byte, kArbitraryMaxPayloadSizeBytes>
kParameters = bytes::MakeArray<const std::byte>(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<ConstByteSpan> encode_result = packet.Encode(packet_buffer_);
ASSERT_EQ(OkStatus(), encode_result.status());
constexpr std::array<const std::byte,
CommandPacket::kHeaderSizeBytes +
kArbitraryMaxPayloadSizeBytes>
kExpectedEncodedPacket = bytes::MakeArray<const std::byte>(
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<CommandPacket> 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<ConstByteSpan> 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<ConstByteSpan> encode_result = packet.Encode(packet_buffer_);
ASSERT_EQ(OkStatus(), encode_result.status());
constexpr std::array<const std::byte, AsyncDataPacket::kHeaderSizeBytes>
kExpectedEncodedPacket = bytes::MakeArray<const std::byte>(
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<AsyncDataPacket> 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<const std::byte, kArbitraryMaxPayloadSizeBytes> kData =
bytes::MakeArray<const std::byte>(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<ConstByteSpan> encode_result = packet.Encode(packet_buffer_);
ASSERT_EQ(OkStatus(), encode_result.status());
constexpr std::array<const std::byte,
AsyncDataPacket::kHeaderSizeBytes +
kArbitraryMaxPayloadSizeBytes>
kExpectedEncodedPacket = bytes::MakeArray<const std::byte>(
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<AsyncDataPacket> 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<ConstByteSpan> 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<ConstByteSpan> encode_result = packet.Encode(packet_buffer_);
ASSERT_EQ(OkStatus(), encode_result.status());
constexpr std::array<const std::byte, SyncDataPacket::kHeaderSizeBytes>
kExpectedEncodedPacket = bytes::MakeArray<const std::byte>(
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<SyncDataPacket> 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<const std::byte, kArbitraryMaxPayloadSizeBytes> kData =
bytes::MakeArray<const std::byte>(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<ConstByteSpan> encode_result = packet.Encode(packet_buffer_);
ASSERT_EQ(OkStatus(), encode_result.status());
constexpr std::array<const std::byte,
SyncDataPacket::kHeaderSizeBytes +
kArbitraryMaxPayloadSizeBytes>
kExpectedEncodedPacket = bytes::MakeArray<const std::byte>(
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<SyncDataPacket> 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<ConstByteSpan> 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<ConstByteSpan> encode_result = packet.Encode(packet_buffer_);
ASSERT_EQ(OkStatus(), encode_result.status());
constexpr std::array<const std::byte, EventPacket::kHeaderSizeBytes>
kExpectedEncodedPacket =
bytes::MakeArray<const std::byte>(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<EventPacket> 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<const std::byte, kArbitraryMaxPayloadSizeBytes>
kParameters = bytes::MakeArray<const std::byte>(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<ConstByteSpan> encode_result = packet.Encode(packet_buffer_);
ASSERT_EQ(OkStatus(), encode_result.status());
constexpr std::array<const std::byte,
EventPacket::kHeaderSizeBytes +
kArbitraryMaxPayloadSizeBytes>
kExpectedEncodedPacket =
bytes::MakeArray<const std::byte>(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<EventPacket> 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