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