// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/device/bluetooth/le/le_scan_result.h"
#include "base/containers/contains.h"
#include "chromecast/device/bluetooth/bluetooth_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromecast {
namespace bluetooth {
TEST(LeScanResultTest, SetAdvData) {
static const uint8_t kBadData[] = {0x3, 0x2};
LeScanResult scan_result;
// Setting invalid data should not change the object.
EXPECT_FALSE(scan_result.SetAdvData({kBadData}));
EXPECT_TRUE(scan_result.adv_data.empty());
EXPECT_TRUE(scan_result.type_to_data.empty());
const std::vector<uint8_t> kFlags = {0x47};
const std::vector<uint8_t> kName = {0x41, 0x42, 0x43};
const std::vector<uint8_t> kService = {0x12, 0x34};
std::vector<uint8_t> adv_data;
adv_data.push_back(kFlags.size() + 1);
adv_data.push_back(LeScanResult::kGapFlags);
adv_data.insert(adv_data.end(), kFlags.begin(), kFlags.end());
adv_data.push_back(kName.size() + 1);
adv_data.push_back(LeScanResult::kGapCompleteName);
adv_data.insert(adv_data.end(), kName.begin(), kName.end());
adv_data.push_back(kService.size() + 1);
adv_data.push_back(LeScanResult::kGapComplete16BitServiceUuids);
adv_data.insert(adv_data.end(), kService.begin(), kService.end());
EXPECT_TRUE(scan_result.SetAdvData(adv_data));
EXPECT_EQ(adv_data, scan_result.adv_data);
ASSERT_EQ(1ul, scan_result.type_to_data[LeScanResult::kGapFlags].size());
EXPECT_EQ(kFlags, scan_result.type_to_data[LeScanResult::kGapFlags][0]);
ASSERT_EQ(1ul,
scan_result.type_to_data[LeScanResult::kGapCompleteName].size());
EXPECT_EQ(kName, scan_result.type_to_data[LeScanResult::kGapCompleteName][0]);
ASSERT_EQ(
1ul, scan_result.type_to_data[LeScanResult::kGapComplete16BitServiceUuids]
.size());
EXPECT_EQ(
kService,
scan_result.type_to_data[LeScanResult::kGapComplete16BitServiceUuids][0]);
}
TEST(LeScanResultTest, Name) {
LeScanResult scan_result;
EXPECT_FALSE(scan_result.Name());
static const char kName1[] = "foo";
static const char kName2[] = "foobar";
scan_result.type_to_data[LeScanResult::kGapShortName].push_back(
std::vector<uint8_t>(
reinterpret_cast<const uint8_t*>(kName1),
reinterpret_cast<const uint8_t*>(kName1) + strlen(kName1)));
std::optional<std::string> name = scan_result.Name();
ASSERT_TRUE(name);
EXPECT_EQ(kName1, *name);
scan_result.type_to_data[LeScanResult::kGapCompleteName].push_back(
std::vector<uint8_t>(
reinterpret_cast<const uint8_t*>(kName2),
reinterpret_cast<const uint8_t*>(kName2) + strlen(kName2)));
name = scan_result.Name();
ASSERT_TRUE(name);
EXPECT_EQ(kName2, *name);
}
TEST(LeScanResultTest, Flags) {
static const uint8_t kFlags = 0x42;
LeScanResult scan_result;
EXPECT_FALSE(scan_result.Flags());
scan_result.type_to_data[LeScanResult::kGapFlags].push_back({kFlags});
auto flags = scan_result.Flags();
ASSERT_TRUE(flags);
EXPECT_EQ(kFlags, *flags);
}
TEST(LeScanResultTest, AllUuids) {
static const uint16_t kIncompleteUuid16 = 0x1234;
const std::vector<uint8_t> kIncompleteUuid16Bytes = {0x34, 0x12};
static const uint16_t kCompleteUuid16 = 0x5678;
const std::vector<uint8_t> kCompleteUuid16Bytes = {0x78, 0x56};
static const uint32_t kIncompleteUuid32 = 0x12345678;
const std::vector<uint8_t> kIncompleteUuid32Bytes = {0x78, 0x56, 0x34, 0x12};
static const uint32_t kCompleteUuid32 = 0xabcdef01;
const std::vector<uint8_t> kCompleteUuid32Bytes = {0x1, 0xef, 0xcd, 0xab};
static const bluetooth_v2_shlib::Uuid kIncompleteUuid128 = {
{0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9b, 0x12, 0xd3, 0xa4, 0x56, 0x42, 0x66,
0x55, 0x44, 0x00, 0x00}};
static const bluetooth_v2_shlib::Uuid kCompleteUuid128 = {
{0xa8, 0x22, 0xc8, 0x85, 0xaf, 0x02, 0xc7, 0x80, 0x9d, 0x4d, 0xbd, 0x9a,
0x1f, 0xa0, 0x6d, 0x93}};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapIncomplete16BitServiceUuids]
.push_back(kIncompleteUuid16Bytes);
scan_result.type_to_data[LeScanResult::kGapComplete16BitServiceUuids]
.push_back(kCompleteUuid16Bytes);
scan_result.type_to_data[LeScanResult::kGapIncomplete32BitServiceUuids]
.push_back(kIncompleteUuid32Bytes);
scan_result.type_to_data[LeScanResult::kGapComplete32BitServiceUuids]
.push_back(kCompleteUuid32Bytes);
scan_result.type_to_data[LeScanResult::kGapIncomplete128BitServiceUuids]
.emplace_back(kIncompleteUuid128.rbegin(), kIncompleteUuid128.rend());
scan_result.type_to_data[LeScanResult::kGapComplete128BitServiceUuids]
.emplace_back(kCompleteUuid128.rbegin(), kCompleteUuid128.rend());
auto all_uuids = scan_result.AllServiceUuids();
ASSERT_TRUE(all_uuids);
ASSERT_EQ(6ul, all_uuids->size());
auto exists = [&all_uuids](const bluetooth_v2_shlib::Uuid& uuid) {
return base::Contains(*all_uuids, uuid);
};
EXPECT_TRUE(exists(util::UuidFromInt16(kIncompleteUuid16)));
EXPECT_TRUE(exists(util::UuidFromInt16(kCompleteUuid16)));
EXPECT_TRUE(exists(util::UuidFromInt32(kIncompleteUuid32)));
EXPECT_TRUE(exists(util::UuidFromInt32(kCompleteUuid32)));
EXPECT_TRUE(exists(kIncompleteUuid128));
EXPECT_TRUE(exists(kCompleteUuid128));
}
TEST(LeScanResultTest, IncompleteListOf16BitServiceUuid) {
static const uint16_t kUuid1 = 0x1234;
const std::vector<uint8_t> kUuid1Bytes = {0x34, 0x12};
static const uint16_t kUuid2 = 0x5678;
const std::vector<uint8_t> kUuid2Bytes = {0x78, 0x56};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapIncomplete16BitServiceUuids]
.push_back(kUuid1Bytes);
scan_result.type_to_data[LeScanResult::kGapIncomplete16BitServiceUuids]
.push_back(kUuid2Bytes);
auto uuids = scan_result.IncompleteListOf16BitServiceUuids();
ASSERT_TRUE(uuids);
ASSERT_EQ(2ul, uuids->size());
EXPECT_EQ(util::UuidFromInt16(kUuid1), (*uuids)[0]);
EXPECT_EQ(util::UuidFromInt16(kUuid2), (*uuids)[1]);
}
TEST(LeScanResultTest, CompleteListOf16BitServiceUuid) {
static const uint16_t kUuid1 = 0x1234;
const std::vector<uint8_t> kUuid1Bytes = {0x34, 0x12};
static const uint16_t kUuid2 = 0x5678;
const std::vector<uint8_t> kUuid2Bytes = {0x78, 0x56};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapComplete16BitServiceUuids]
.push_back(kUuid1Bytes);
scan_result.type_to_data[LeScanResult::kGapComplete16BitServiceUuids]
.push_back(kUuid2Bytes);
auto uuids = scan_result.CompleteListOf16BitServiceUuids();
ASSERT_TRUE(uuids);
ASSERT_EQ(2ul, uuids->size());
EXPECT_EQ(util::UuidFromInt16(kUuid1), (*uuids)[0]);
EXPECT_EQ(util::UuidFromInt16(kUuid2), (*uuids)[1]);
}
TEST(LeScanResultTest, IncompleteListOf32BitServiceUuid) {
static const uint32_t kUuid1 = 0x12345678;
const std::vector<uint8_t> kUuid1Bytes = {0x78, 0x56, 0x34, 0x12};
static const uint32_t kUuid2 = 0xabcdef01;
const std::vector<uint8_t> kUuid2Bytes = {0x1, 0xef, 0xcd, 0xab};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapIncomplete32BitServiceUuids]
.push_back(kUuid1Bytes);
scan_result.type_to_data[LeScanResult::kGapIncomplete32BitServiceUuids]
.push_back(kUuid2Bytes);
auto uuids = scan_result.IncompleteListOf32BitServiceUuids();
ASSERT_TRUE(uuids);
ASSERT_EQ(2ul, uuids->size());
EXPECT_EQ(util::UuidFromInt32(kUuid1), (*uuids)[0]);
EXPECT_EQ(util::UuidFromInt32(kUuid2), (*uuids)[1]);
}
TEST(LeScanResultTest, CompleteListOf32BitServiceUuid) {
static const uint32_t kUuid1 = 0x12345678;
const std::vector<uint8_t> kUuid1Bytes = {0x78, 0x56, 0x34, 0x12};
static const uint32_t kUuid2 = 0xabcdef01;
const std::vector<uint8_t> kUuid2Bytes = {0x1, 0xef, 0xcd, 0xab};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapComplete32BitServiceUuids]
.push_back(kUuid1Bytes);
scan_result.type_to_data[LeScanResult::kGapComplete32BitServiceUuids]
.push_back(kUuid2Bytes);
auto uuids = scan_result.CompleteListOf32BitServiceUuids();
ASSERT_TRUE(uuids);
ASSERT_EQ(2ul, uuids->size());
EXPECT_EQ(util::UuidFromInt32(kUuid1), (*uuids)[0]);
EXPECT_EQ(util::UuidFromInt32(kUuid2), (*uuids)[1]);
}
TEST(LeScanResultTest, IncompleteListOf128BitServiceUuid) {
static const bluetooth_v2_shlib::Uuid kUuid1 = {
{0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9b, 0x12, 0xd3, 0xa4, 0x56, 0x42, 0x66,
0x55, 0x44, 0x00, 0x00}};
static const bluetooth_v2_shlib::Uuid kUuid2 = {
{0xa8, 0x22, 0xc8, 0x85, 0xaf, 0x02, 0xc7, 0x80, 0x9d, 0x4d, 0xbd, 0x9a,
0x1f, 0xa0, 0x6d, 0x93}};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapIncomplete128BitServiceUuids]
.emplace_back(kUuid1.rbegin(), kUuid1.rend());
scan_result.type_to_data[LeScanResult::kGapIncomplete128BitServiceUuids]
.emplace_back(kUuid2.rbegin(), kUuid2.rend());
auto uuids = scan_result.IncompleteListOf128BitServiceUuids();
ASSERT_TRUE(uuids);
ASSERT_EQ(2ul, uuids->size());
EXPECT_EQ(kUuid1, (*uuids)[0]);
EXPECT_EQ(kUuid2, (*uuids)[1]);
}
TEST(LeScanResultTest, CompleteListOf128BitServiceUuid) {
static const bluetooth_v2_shlib::Uuid kUuid1 = {
{0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9b, 0x12, 0xd3, 0xa4, 0x56, 0x42, 0x66,
0x55, 0x44, 0x00, 0x00}};
static const bluetooth_v2_shlib::Uuid kUuid2 = {
{0xa8, 0x22, 0xc8, 0x85, 0xaf, 0x02, 0xc7, 0x80, 0x9d, 0x4d, 0xbd, 0x9a,
0x1f, 0xa0, 0x6d, 0x93}};
static const bluetooth_v2_shlib::Uuid kUuid3 = {
{0xaa, 0x22, 0xc8, 0x85, 0xaf, 0x02, 0xc7, 0x80, 0x9d, 0x4d, 0xbd, 0x9a,
0x1f, 0xa0, 0x6d, 0x93}};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapComplete128BitServiceUuids]
.emplace_back(kUuid1.rbegin(), kUuid1.rend());
scan_result.type_to_data[LeScanResult::kGapComplete128BitServiceUuids]
.emplace_back(kUuid2.rbegin(), kUuid2.rend());
auto& end =
scan_result.type_to_data[LeScanResult::kGapComplete128BitServiceUuids]
.back();
end.insert(end.end(), kUuid3.rbegin(), kUuid3.rend());
auto uuids = scan_result.CompleteListOf128BitServiceUuids();
ASSERT_TRUE(uuids);
ASSERT_EQ(3ul, uuids->size());
EXPECT_EQ(kUuid1, (*uuids)[0]);
EXPECT_EQ(kUuid2, (*uuids)[1]);
EXPECT_EQ(kUuid3, (*uuids)[2]);
}
TEST(LeScanResultTest, AllServiceData) {
static const uint16_t kUuid16 = 0x1234;
const std::vector<uint8_t> kUuid16Bytes = {0x34, 0x12, 0xab, 0xcd, 0xef};
static const uint32_t kUuid32 = 0x12345678;
const std::vector<uint8_t> kUuid32Bytes = {0x78, 0x56, 0x34, 0x12,
0xab, 0xcd, 0xef};
static const bluetooth_v2_shlib::Uuid kUuid128 = {
{0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9b, 0x12, 0xd3, 0xa4, 0x56, 0x42, 0x66,
0x55, 0x44, 0x00, 0x00}};
const std::vector<uint8_t> kUuid128Data = {0x78, 0x56, 0x34, 0x12,
0xab, 0xcd, 0xef};
std::vector<uint8_t> uuid128_bytes(kUuid128.rbegin(), kUuid128.rend());
uuid128_bytes.insert(uuid128_bytes.end(), kUuid128Data.begin(),
kUuid128Data.end());
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapServicesData16bit].push_back(
kUuid16Bytes);
scan_result.type_to_data[LeScanResult::kGapServicesData32bit].push_back(
kUuid32Bytes);
scan_result.type_to_data[LeScanResult::kGapServicesData128bit].push_back(
uuid128_bytes);
auto sd = scan_result.AllServiceData();
EXPECT_EQ(3ul, sd.size());
EXPECT_EQ(sd[util::UuidFromInt16(kUuid16)],
std::vector<uint8_t>(kUuid16Bytes.begin() + sizeof(kUuid16),
kUuid16Bytes.end()));
EXPECT_EQ(sd[util::UuidFromInt32(kUuid32)],
std::vector<uint8_t>(kUuid32Bytes.begin() + sizeof(kUuid32),
kUuid32Bytes.end()));
EXPECT_EQ(sd[kUuid128], kUuid128Data);
}
TEST(LeScanResultTest, ServiceData16Bit) {
static const uint16_t kUuid1 = 0x1234;
const std::vector<uint8_t> kUuid1Bytes = {0x34, 0x12, 0xab, 0xcd, 0xef};
static const uint16_t kUuid2 = 0x5678;
const std::vector<uint8_t> kUuid2Bytes = {0x78, 0x56, 0xa1, 0x0d, 0xe1};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapServicesData16bit].push_back(
kUuid1Bytes);
scan_result.type_to_data[LeScanResult::kGapServicesData16bit].push_back(
kUuid2Bytes);
auto sd = scan_result.ServiceData16Bit();
ASSERT_EQ(2ul, sd.size());
EXPECT_EQ(sd[util::UuidFromInt16(kUuid1)],
std::vector<uint8_t>(kUuid1Bytes.begin() + sizeof(kUuid1),
kUuid1Bytes.end()));
EXPECT_EQ(sd[util::UuidFromInt16(kUuid2)],
std::vector<uint8_t>(kUuid2Bytes.begin() + sizeof(kUuid2),
kUuid2Bytes.end()));
}
TEST(LeScanResultTest, ServiceData32Bit) {
static const uint32_t kUuid1 = 0x12345678;
const std::vector<uint8_t> kUuid1Bytes = {0x78, 0x56, 0x34, 0x12,
0xab, 0xcd, 0xef};
static const uint32_t kUuid2 = 0xabcdef01;
const std::vector<uint8_t> kUuid2Bytes = {0x01, 0xef, 0xcd, 0xab,
0xa1, 0x0d, 0xe1};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapServicesData32bit].push_back(
kUuid1Bytes);
scan_result.type_to_data[LeScanResult::kGapServicesData32bit].push_back(
kUuid2Bytes);
auto sd = scan_result.ServiceData32Bit();
ASSERT_EQ(2ul, sd.size());
EXPECT_EQ(sd[util::UuidFromInt32(kUuid1)],
std::vector<uint8_t>(kUuid1Bytes.begin() + sizeof(kUuid1),
kUuid1Bytes.end()));
EXPECT_EQ(sd[util::UuidFromInt32(kUuid2)],
std::vector<uint8_t>(kUuid2Bytes.begin() + sizeof(kUuid2),
kUuid2Bytes.end()));
}
TEST(LeScanResultTest, ServiceData128Bit) {
static const bluetooth_v2_shlib::Uuid kUuid1 = {
{0x12, 0x3e, 0x45, 0x67, 0xe8, 0x9b, 0x12, 0xd3, 0xa4, 0x56, 0x42, 0x66,
0x55, 0x44, 0x00, 0x00}};
const std::vector<uint8_t> kUuid1Data = {0x78, 0x56, 0x34, 0x12,
0xab, 0xcd, 0xef};
std::vector<uint8_t> uuid1_bytes(kUuid1.rbegin(), kUuid1.rend());
uuid1_bytes.insert(uuid1_bytes.end(), kUuid1Data.begin(), kUuid1Data.end());
static const bluetooth_v2_shlib::Uuid kUuid2 = {
{0xa8, 0x22, 0xc8, 0x85, 0xaf, 0x02, 0xc7, 0x80, 0x9d, 0x4d, 0xbd, 0x9a,
0x1f, 0xa0, 0x6d, 0x93}};
const std::vector<uint8_t> kUuid2Data = {0x01, 0xef, 0xcd, 0xab,
0xa1, 0x0d, 0xe1};
std::vector<uint8_t> uuid2_bytes(kUuid2.rbegin(), kUuid2.rend());
uuid2_bytes.insert(uuid2_bytes.end(), kUuid2Data.begin(), kUuid2Data.end());
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapServicesData128bit].push_back(
uuid1_bytes);
scan_result.type_to_data[LeScanResult::kGapServicesData128bit].push_back(
uuid2_bytes);
auto sd = scan_result.ServiceData128Bit();
ASSERT_EQ(2ul, sd.size());
EXPECT_EQ(sd[kUuid1], kUuid1Data);
EXPECT_EQ(sd[kUuid2], kUuid2Data);
}
TEST(LeScanResultTest, ManufacturerData) {
static const uint16_t kManufacturer1 = 0x1234;
const std::vector<uint8_t> kManufacturer1Bytes = {0x34, 0x12, 0xab, 0xcd,
0xef};
static const uint16_t kManufacturer2 = 0x5678;
const std::vector<uint8_t> kManufacturer2Bytes = {0x78, 0x56, 0xa1, 0x0d,
0xe1};
LeScanResult scan_result;
scan_result.type_to_data[LeScanResult::kGapManufacturerData].push_back(
kManufacturer1Bytes);
scan_result.type_to_data[LeScanResult::kGapManufacturerData].push_back(
kManufacturer2Bytes);
auto md = scan_result.ManufacturerData();
ASSERT_EQ(2ul, md.size());
EXPECT_EQ(
md[kManufacturer1],
std::vector<uint8_t>(kManufacturer1Bytes.begin() + sizeof(kManufacturer1),
kManufacturer1Bytes.end()));
EXPECT_EQ(
md[kManufacturer2],
std::vector<uint8_t>(kManufacturer2Bytes.begin() + sizeof(kManufacturer2),
kManufacturer2Bytes.end()));
}
} // namespace bluetooth
} // namespace chromecast