1 /*
2 * Copyright 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "discovery/device/data_parser.h"
18
19 #include <bluetooth/log.h>
20
21 #include <algorithm>
22
23 #include "gtest/gtest.h"
24 #include "hci/hci_packets.h"
25
26 using namespace bluetooth::hci;
27 using bluetooth::discovery::device::DataParser;
28
29 namespace {
30 constexpr uint8_t kOneFlag32Data[] = {
31 0x5, static_cast<uint8_t>(GapDataType::FLAGS), 0xde, 0xad, 0xbe, 0xef};
32 constexpr uint8_t kTwoFlag32Data[] = {
33 0x5,
34 static_cast<uint8_t>(GapDataType::FLAGS),
35 0xde,
36 0xad,
37 0xbe,
38 0xef,
39 0x5,
40 static_cast<uint8_t>(GapDataType::FLAGS),
41 0x11,
42 0x22,
43 0x33,
44 0x44};
45 constexpr uint8_t kNoUuid16Data[] = {
46 0x2, static_cast<uint8_t>(GapDataType::COMPLETE_LIST_16_BIT_UUIDS)};
47 constexpr uint8_t kPartialUuid16Data[] = {
48 0x2, static_cast<uint8_t>(GapDataType::COMPLETE_LIST_16_BIT_UUIDS), 0x12};
49 constexpr uint8_t kOneUuid16Data[] = {
50 0x3, static_cast<uint8_t>(GapDataType::COMPLETE_LIST_16_BIT_UUIDS), 0x12, 0x34};
51
toLeInt(const std::vector<uint8_t> & v)52 uint32_t toLeInt(const std::vector<uint8_t>& v) {
53 return v[3] | (v[2] << 8) | (v[1] << 16) | (v[0] << 24);
54 }
55
56 } // namespace
57
TEST(DataParserTest,no_data)58 TEST(DataParserTest, no_data) {
59 auto data = std::make_shared<std::vector<uint8_t>>();
60
61 auto it = Iterator<kLittleEndian>(data);
62 GapData gap_data;
63 it = GapData::Parse(&gap_data, it);
64
65 ASSERT_EQ(it.NumBytesRemaining(), 0U);
66 }
67
TEST(DataParserTest,one_element_data)68 TEST(DataParserTest, one_element_data) {
69 auto data = std::make_shared<std::vector<uint8_t>>(1);
70 data->push_back(0xff);
71
72 auto it = Iterator<kLittleEndian>(data);
73 GapData gap_data;
74 it = GapData::Parse(&gap_data, it);
75
76 ASSERT_EQ(it.NumBytesRemaining(), 0U);
77 }
78
TEST(DataParserTest,two_element_data)79 TEST(DataParserTest, two_element_data) {
80 auto data = std::make_shared<std::vector<uint8_t>>(2);
81 data->push_back(0xff);
82 data->push_back(0xff);
83
84 auto it = Iterator<kLittleEndian>(data);
85 GapData gap_data;
86 it = GapData::Parse(&gap_data, it);
87
88 ASSERT_EQ(it.NumBytesRemaining(), 0U);
89 }
90
TEST(DataParserTest,all_ones_data)91 TEST(DataParserTest, all_ones_data) {
92 auto data = std::make_shared<std::vector<uint8_t>>(256);
93 std::fill(data->begin(), data->end(), 0xff);
94
95 auto it = Iterator<kLittleEndian>(data);
96 GapData gap_data;
97 it = GapData::Parse(&gap_data, it);
98
99 ASSERT_EQ(it.NumBytesRemaining(), 0U);
100 }
101
TEST(DataParserTest,simple_flag)102 TEST(DataParserTest, simple_flag) {
103 auto data = std::make_shared<std::vector<uint8_t>>(
104 kOneFlag32Data, kOneFlag32Data + sizeof(kOneFlag32Data));
105
106 auto it = Iterator<kLittleEndian>(data);
107 GapData gap_data;
108 it = GapData::Parse(&gap_data, it);
109
110 ASSERT_EQ(it.NumBytesRemaining(), 0U);
111 ASSERT_EQ(gap_data.data_type_, GapDataType::FLAGS);
112 ASSERT_EQ(0xdeadbeef, toLeInt(gap_data.data_));
113 }
114
TEST(DataParserTest,two_flags)115 TEST(DataParserTest, two_flags) {
116 auto data = std::make_shared<std::vector<uint8_t>>(
117 kTwoFlag32Data, kTwoFlag32Data + sizeof(kTwoFlag32Data));
118
119 auto it = Iterator<kLittleEndian>(data);
120 GapData gap_data[2];
121 it = GapData::Parse(&gap_data[0], it);
122
123 ASSERT_EQ(it.NumBytesRemaining(), 1U /* length */ + 1U /* type */ + 4U /* data */);
124 ASSERT_EQ(gap_data[0].data_type_, GapDataType::FLAGS);
125 ASSERT_EQ((unsigned)0xdeadbeef, toLeInt(gap_data[0].data_));
126
127 it = GapData::Parse(&gap_data[1], it);
128
129 ASSERT_EQ(it.NumBytesRemaining(), 0U);
130 ASSERT_EQ(gap_data[1].data_type_, GapDataType::FLAGS);
131 ASSERT_EQ((unsigned)0x11223344, toLeInt(gap_data[1].data_));
132 }
133
TEST(DataParserTest,no_uuid16)134 TEST(DataParserTest, no_uuid16) {
135 auto data =
136 std::make_shared<std::vector<uint8_t>>(kNoUuid16Data, kNoUuid16Data + sizeof(kNoUuid16Data));
137
138 auto it = Iterator<kLittleEndian>(data);
139 GapData gap_data;
140 it = GapData::Parse(&gap_data, it);
141
142 ASSERT_EQ(it.NumBytesRemaining(), 0U);
143 ASSERT_EQ(gap_data.data_type_, GapDataType::COMPLETE_LIST_16_BIT_UUIDS);
144 ASSERT_EQ(0U, gap_data.data_.size());
145 }
146
TEST(DataParserTest,partial_uuid16)147 TEST(DataParserTest, partial_uuid16) {
148 auto data = std::make_shared<std::vector<uint8_t>>(
149 kPartialUuid16Data, kPartialUuid16Data + sizeof(kPartialUuid16Data));
150
151 auto it = Iterator<kLittleEndian>(data);
152 GapData gap_data;
153 it = GapData::Parse(&gap_data, it);
154
155 ASSERT_EQ(it.NumBytesRemaining(), 0U);
156 ASSERT_EQ(gap_data.data_type_, GapDataType::COMPLETE_LIST_16_BIT_UUIDS);
157 ASSERT_EQ(1U, gap_data.data_.size());
158 }
159
TEST(DataParserTest,one_uuid16)160 TEST(DataParserTest, one_uuid16) {
161 auto data = std::make_shared<std::vector<uint8_t>>(
162 kOneUuid16Data, kOneUuid16Data + sizeof(kOneUuid16Data));
163 auto it = Iterator<kLittleEndian>(data);
164 GapData gap_data;
165 it = GapData::Parse(&gap_data, it);
166
167 ASSERT_EQ(it.NumBytesRemaining(), 0U);
168 ASSERT_EQ(gap_data.data_type_, GapDataType::COMPLETE_LIST_16_BIT_UUIDS);
169 ASSERT_EQ(2U, gap_data.data_.size());
170 }
171
TEST(DataParserTest,simple_data_parser)172 TEST(DataParserTest, simple_data_parser) {
173 std::vector<uint8_t> v(kTwoFlag32Data, kTwoFlag32Data + sizeof(kTwoFlag32Data));
174 DataParser data_parser(v);
175 ASSERT_EQ(2U, data_parser.GetNumGapData());
176
177 std::vector<bluetooth::hci::GapData> flags;
178 std::vector<bluetooth::hci::GapData> gap_data = data_parser.GetData();
179 for (const auto& data : gap_data) {
180 ASSERT_EQ(bluetooth::hci::GapDataType::FLAGS, data.data_type_);
181 flags.push_back(data);
182 }
183
184 ASSERT_EQ(2U, flags.size());
185 uint32_t value[2] = {
186 toLeInt(flags[0].data_),
187 toLeInt(flags[1].data_),
188 };
189 ASSERT_EQ((unsigned)0xdeadbeef, value[0]);
190 ASSERT_EQ((unsigned)0x11223344, value[1]);
191 }
192
TEST(DataParserTest,two_flags_backing_store_cleared)193 TEST(DataParserTest, two_flags_backing_store_cleared) {
194 std::vector<uint8_t>* v = new std::vector<uint8_t>(sizeof(kTwoFlag32Data));
195 std::copy(kTwoFlag32Data, kTwoFlag32Data + sizeof(kTwoFlag32Data), v->begin());
196 DataParser data_parser(*v);
197 v->clear();
198 ASSERT_EQ(2U, data_parser.GetNumGapData());
199
200 std::vector<bluetooth::hci::GapData> flags;
201 std::vector<bluetooth::hci::GapData> gap_data = data_parser.GetData();
202 for (const auto& data : gap_data) {
203 ASSERT_EQ(bluetooth::hci::GapDataType::FLAGS, data.data_type_);
204 flags.push_back(data);
205 }
206
207 ASSERT_EQ(2U, flags.size());
208 uint32_t value[2] = {
209 toLeInt(flags[0].data_),
210 toLeInt(flags[1].data_),
211 };
212 ASSERT_EQ((unsigned)0xdeadbeef, value[0]);
213 ASSERT_EQ((unsigned)0x11223344, value[1]);
214
215 delete v;
216 }
217
TEST(DataParserTest,backing_store_freed)218 TEST(DataParserTest, backing_store_freed) {
219 uint8_t* data = (uint8_t*)malloc(sizeof(kTwoFlag32Data));
220 std::copy(kTwoFlag32Data, kTwoFlag32Data + sizeof(kTwoFlag32Data), data);
221 DataParser data_parser(std::vector<uint8_t>(data, data + sizeof(kTwoFlag32Data)));
222 free(data);
223 ASSERT_EQ(2U, data_parser.GetNumGapData());
224
225 std::vector<bluetooth::hci::GapData> flags;
226 std::vector<bluetooth::hci::GapData> gap_data = data_parser.GetData();
227 for (const auto& data : gap_data) {
228 ASSERT_EQ(bluetooth::hci::GapDataType::FLAGS, data.data_type_);
229 flags.push_back(data);
230 }
231
232 ASSERT_EQ(2U, flags.size());
233 uint32_t value[2] = {
234 toLeInt(flags[0].data_),
235 toLeInt(flags[1].data_),
236 };
237 ASSERT_EQ((unsigned)0xdeadbeef, value[0]);
238 ASSERT_EQ((unsigned)0x11223344, value[1]);
239 }
240
GapDataToString(const GapData & data)241 std::string GapDataToString(const GapData& data) {
242 std::stringstream ss;
243 ss << std::hex << std::showbase << "LengthAndData { ";
244 ss << "data = "
245 << "VECTOR[";
246 for (size_t index = 0; index < data.data_.size(); index++) {
247 ss << ((index == 0) ? "" : ", ") << static_cast<uint64_t>((data.data_[index]));
248 }
249 ss << "]";
250 ss << " }";
251 return ss.str();
252 }
253
TEST(DataParserTest,random)254 TEST(DataParserTest, random) {
255 constexpr int kMaxLoop = 1000;
256 auto data = std::vector<uint8_t>(512);
257
258 for (int i = 0; i < kMaxLoop; i++) {
259 size_t size = rand() % 512;
260 for (size_t i = 0; i < size; i++) {
261 data[i] = rand() % 256;
262 }
263 DataParser data_parser(data);
264
265 if (((i + 1) % 100) == 0) {
266 bluetooth::log::info("loop {}", i);
267 }
268 }
269 }
270