blob: 556d91bf9ea2ceda79959ff15b2ab0454522e941 [file] [log] [blame] [edit]
// Copyright 2024 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/snoop.h"
#include <vector>
#include "pw_bluetooth_proxy/h4_packet.h"
#include "pw_bytes/span.h"
#include "pw_chrono/simulated_system_clock.h"
#include "pw_status/status.h"
#include "pw_unit_test/framework.h"
namespace pw::bluetooth {
namespace {
using ::std::chrono_literals::operator""us;
constexpr uint8_t hex_char_to_int(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
} else {
// Handle invalid characters as needed
return 0;
}
}
std::vector<std::byte> hex_string_to_bytes(std::string_view hex_str) {
std::vector<std::byte> bytes{};
uint8_t value = 0;
for (size_t i = 0; i < hex_str.size(); i++) {
if (i % 2 == 0) {
value = hex_char_to_int(hex_str[i]) << 4;
} else {
value |= hex_char_to_int(hex_str[i]);
bytes.push_back(std::byte(value));
}
}
return bytes;
}
std::vector<std::byte> get_snoop_log(Snoop& snoop) {
std::vector<std::byte> snoop_data;
Status status = snoop.Dump([&snoop_data](ConstByteSpan data) {
for (const std::byte item : data) {
snoop_data.push_back(item);
}
return OkStatus();
});
EXPECT_TRUE(status.ok());
return snoop_data;
}
} // namespace
TEST(SnoopTest, HeaderOnly) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 256> snoop{clock};
std::string_view expected_snoop_data = // Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
TEST(SnoopTest, HeaderTx) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 256> snoop{clock};
// Add packet 1
std::array<uint8_t, 5> tx_data = {0x12, 0x34, 0x56, 0x78, 0x9A};
proxy::H4PacketWithHci packet{emboss::H4PacketType::ACL_DATA, tx_data};
snoop.AddTx(packet);
// Validate
std::string_view expected_snoop_data =
""
// Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea"
// Packet 1
// Original Length (32-bit)
"00000006"
// Included Length (32-bit)
"00000006"
// Packet Flags (32-bit)
"00000000"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000000"
// Packet Data[0] - HCI_TYPE (8-bit)
"02"
// Packet Data[1-N] - Data
"123456789a";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
TEST(SnoopTest, HeaderTxTruncated) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 3> snoop{clock};
// Add packet 1
std::array<uint8_t, 5> tx_data = {0x12, 0x34, 0x56, 0x78, 0x9A};
proxy::H4PacketWithHci packet{emboss::H4PacketType::ACL_DATA, tx_data};
snoop.AddTx(packet);
// Validate
std::string_view expected_snoop_data =
""
// Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea"
// Packet 1
// Original Length (32-bit)
"00000006"
// Included Length (32-bit)
"00000004"
// Packet Flags (32-bit)
"00000000"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000000"
// Packet Data[0] - HCI_TYPE (8-bit)
"02"
// Packet Data[1-N] - Data
"123456";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
TEST(SnoopTest, HeaderRx) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 256> snoop{clock};
// Add packet 1
std::array<uint8_t, 5> rx_data = {0x12, 0x34, 0x56, 0x78, 0x9A};
proxy::H4PacketWithHci packet{emboss::H4PacketType::ACL_DATA, rx_data};
snoop.AddRx(packet);
// Validate
std::string_view expected_snoop_data =
""
// Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea"
// Packet 1
// Original Length (32-bit)
"00000006"
// Included Length (32-bit)
"00000006"
// Packet Flags (32-bit)
"00000001"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000000"
// Packet Data[0] - HCI_TYPE (8-bit)
"02"
// Packet Data[1-N] - Data
"123456789a";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
TEST(SnoopTest, HeaderRxTruncated) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 3> snoop{clock};
// Add packet 1
std::array<uint8_t, 5> rx_data = {0x12, 0x34, 0x56, 0x78, 0x9A};
proxy::H4PacketWithHci packet{emboss::H4PacketType::ACL_DATA, rx_data};
snoop.AddRx(packet);
// Validate
std::string_view expected_snoop_data =
""
// Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea"
// Packet 1
// Original Length (32-bit)
"00000006"
// Included Length (32-bit)
"00000004"
// Packet Flags (32-bit)
"00000001"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000000"
// Packet Data[0] - HCI_TYPE (8-bit)
"02"
// Packet Data[1-N] - Data
"123456";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
TEST(SnoopTest, HeaderTxTx) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 256> snoop{clock};
// Add packet 1
std::array<uint8_t, 5> tx_data1 = {0x12, 0x34, 0x56, 0x78, 0x9A};
proxy::H4PacketWithHci packet1{emboss::H4PacketType::ACL_DATA, tx_data1};
snoop.AddTx(packet1);
// Add packet 2
clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
std::array<uint8_t, 3> tx_data2 = {0xBC, 0xDE, 0xF0};
proxy::H4PacketWithHci packet2{emboss::H4PacketType::COMMAND, tx_data2};
snoop.AddTx(packet2);
// Validate
std::string_view expected_snoop_data =
""
// Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea"
// Packet 1
// Original Length (32-bit)
"00000006"
// Included Length (32-bit)
"00000006"
// Packet Flags (32-bit)
"00000000"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000000"
// Packet Data[0] - HCI_TYPE (8-bit)
"02"
// Packet Data[1-N] - Data
"123456789a"
// Packet 2
// Original Length (32-bit)
"00000004"
// Included Length (32-bit)
"00000004"
// Packet Flags (32-bit)
"00000000"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000001"
// Packet Data[0] - HCI_TYPE (8-bit)
"01"
// Packet Data[1-N] - Data
"BCDEF0";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
TEST(SnoopTest, HeaderRxRx) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 256> snoop{clock};
// Add packet 1
std::array<uint8_t, 5> rx_data1 = {0x12, 0x34, 0x56, 0x78, 0x9A};
proxy::H4PacketWithHci packet1{emboss::H4PacketType::ACL_DATA, rx_data1};
snoop.AddRx(packet1);
// Add packet 2
clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
std::array<uint8_t, 3> rx_data2 = {0xBC, 0xDE, 0xF0};
proxy::H4PacketWithHci packet2{emboss::H4PacketType::COMMAND, rx_data2};
snoop.AddRx(packet2);
// Validate
std::string_view expected_snoop_data =
""
// Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea"
// Packet 1
// Original Length (32-bit)
"00000006"
// Included Length (32-bit)
"00000006"
// Packet Flags (32-bit)
"00000001"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000000"
// Packet Data[0] - HCI_TYPE (8-bit)
"02"
// Packet Data[1-N] - Data
"123456789a"
// Packet 2
// Original Length (32-bit)
"00000004"
// Included Length (32-bit)
"00000004"
// Packet Flags (32-bit)
"00000001"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000001"
// Packet Data[0] - HCI_TYPE (8-bit)
"01"
// Packet Data[1-N] - Data
"BCDEF0";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
TEST(SnoopTest, HeaderRxTxRxTx) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 256> snoop{clock};
// Add packet 1
std::array<uint8_t, 5> rx_data1 = {0x12, 0x34, 0x56, 0x78, 0x9A};
proxy::H4PacketWithHci packet1{emboss::H4PacketType::ACL_DATA, rx_data1};
snoop.AddRx(packet1);
// Add packet 2
clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
std::array<uint8_t, 3> tx_data1 = {0xBC, 0xDE, 0xF0};
proxy::H4PacketWithHci packet2{emboss::H4PacketType::COMMAND, tx_data1};
snoop.AddTx(packet2);
// Add packet 3
clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
std::array<uint8_t, 5> rx_data2 = {0x21, 0x43, 0x65, 0x87, 0xA9};
proxy::H4PacketWithHci packet3{emboss::H4PacketType::ACL_DATA, rx_data2};
snoop.AddRx(packet3);
// Add packet 4
clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
std::array<uint8_t, 3> tx_data2 = {0xCB, 0xED, 0x0F};
proxy::H4PacketWithHci packet4{emboss::H4PacketType::COMMAND, tx_data2};
snoop.AddTx(packet4);
// Validate
std::string_view expected_snoop_data =
""
// Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea"
// Packet 1
// Original Length (32-bit)
"00000006"
// Included Length (32-bit)
"00000006"
// Packet Flags (32-bit)
"00000001"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000000"
// Packet Data[0] - HCI_TYPE (8-bit)
"02"
// Packet Data[1-N] - Data
"123456789a"
// Packet 2
// Original Length (32-bit)
"00000004"
// Included Length (32-bit)
"00000004"
// Packet Flags (32-bit)
"00000000"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000001"
// Packet Data[0] - HCI_TYPE (8-bit)
"01"
// Packet Data[1-N] - Data
"BCDEF0"
// Packet 3
// Original Length (32-bit)
"00000006"
// Included Length (32-bit)
"00000006"
// Packet Flags (32-bit)
"00000001"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000002"
// Packet Data[0] - HCI_TYPE (8-bit)
"02"
// Packet Data[1-N] - Data
"21436587a9"
// Packet 4
// Original Length (32-bit)
"00000004"
// Included Length (32-bit)
"00000004"
// Packet Flags (32-bit)
"00000000"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000003"
// Packet Data[0] - HCI_TYPE (8-bit)
"01"
// Packet Data[1-N] - Data
"CBED0F";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
TEST(SnoopTest, Disabled) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 256> snoop{clock};
// Disable
snoop.Disable();
// Add packet 1
std::array<uint8_t, 5> rx_data1 = {0x12, 0x34, 0x56, 0x78, 0x9A};
proxy::H4PacketWithHci packet1{emboss::H4PacketType::ACL_DATA, rx_data1};
snoop.AddRx(packet1);
// Validate
std::string_view expected_snoop_data =
""
// Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
TEST(SnoopTest, DisabledEnable) {
chrono::SimulatedSystemClock clock{};
SnoopBuffer<4096, 256> snoop{clock};
// Disable
snoop.Disable();
// Add packet 1
std::array<uint8_t, 5> rx_data1 = {0x12, 0x34, 0x56, 0x78, 0x9A};
proxy::H4PacketWithHci packet1{emboss::H4PacketType::ACL_DATA, rx_data1};
snoop.AddRx(packet1);
// Renable
snoop.Enable();
// Add packet 2
clock.AdvanceTime(pw::chrono::SystemClock::for_at_least(1us));
std::array<uint8_t, 3> tx_data1 = {0xBC, 0xDE, 0xF0};
proxy::H4PacketWithHci packet2{emboss::H4PacketType::COMMAND, tx_data1};
snoop.AddTx(packet2);
// Validate
std::string_view expected_snoop_data =
""
// Identification Pattern (64-bit)
"6274736e6f6f7000"
// Version Number (32-bit)
"00000001"
// Datalink Type (32-bit)
"000003ea"
// Packet 2
// Original Length (32-bit)
"00000004"
// Included Length (32-bit)
"00000004"
// Packet Flags (32-bit)
"00000000"
// Cumulative Drops (32-bit)
"00000000"
// Timestamp Microseconds (64-bit)
"0000000000000001"
// Packet Data[0] - HCI_TYPE (8-bit)
"01"
// Packet Data[1-N] - Data
"BCDEF0";
EXPECT_EQ(hex_string_to_bytes(expected_snoop_data), get_snoop_log(snoop));
}
} // namespace pw::bluetooth