1 /*
2  * Copyright 2018 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 <base/logging.h>
18 #include <gtest/gtest.h>
19 
20 #include "common/data_element_reader.h"
21 
22 namespace bluetooth {
23 namespace sdp {
24 
25 using namespace testing;
26 using DataElement = DataElementReader::DataElement;
27 
28 // A helper class to help work with the Data Element classes.
29 class ReaderPacket : public ::bluetooth::Packet {
30  public:
31   using Packet::Packet;
32 
Make(std::vector<uint8_t> payload)33   static std::shared_ptr<ReaderPacket> Make(std::vector<uint8_t> payload) {
34     auto pkt = std::shared_ptr<ReaderPacket>(new ReaderPacket());
35     pkt->packet_start_index_ = 0;
36     pkt->packet_end_index_ = payload.size();
37     pkt->data_ = std::make_shared<std::vector<uint8_t>>(std::move(payload));
38     return pkt;
39   }
40 
ToString() const41   std::string ToString() const override { return ""; }
IsValid() const42   bool IsValid() const override { return true; }
GetPayloadIndecies() const43   std::pair<size_t, size_t> GetPayloadIndecies() const override {
44     return std::pair<size_t, size_t>(packet_start_index_, packet_end_index_);
45   }
46 };
47 
48 bool operator!=(DataElementReader a, DataElementReader b);
49 
50 // A helper function to help compare DataElementReader objects.
operator ==(DataElementReader a,DataElementReader b)51 bool operator==(DataElementReader a, DataElementReader b) {
52   while (true) {
53     DataElement a_elem = a.ReadNext();
54     DataElement b_elem = b.ReadNext();
55 
56     if (a_elem != b_elem) return false;
57 
58     // If we get here that means both a and b have reached the end.
59     if (a_elem == DataElement(std::monostate())) break;
60   }
61 
62   return true;
63 }
64 
operator !=(DataElementReader a,DataElementReader b)65 bool operator!=(DataElementReader a, DataElementReader b) { return !(a == b); }
66 
67 // A helper function to convert a type and a size to a descriptor byte.
Desc(DataElementType t,DataElementSize s)68 constexpr uint8_t Desc(DataElementType t, DataElementSize s) {
69   return static_cast<uint8_t>(t) << 3 | static_cast<uint8_t>(s);
70 }
71 
72 // Helper that can create a Data Element reader from a vector.
CreateReader(std::vector<uint8_t> payload)73 DataElementReader CreateReader(std::vector<uint8_t> payload) {
74   auto packet = ReaderPacket::Make(std::move(payload));
75   return DataElementReader(packet->begin(), packet->end());
76 }
77 
78 // Test all the valid cases of reading the next Data Element.
79 using ValidTestParam = std::tuple<std::vector<uint8_t>, DataElement>;
80 class ValidReadTest : public TestWithParam<ValidTestParam> {};
81 
82 std::vector<ValidTestParam> valid_values = {
83     // Boolean Tests
84     ValidTestParam{
85         {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01},
86         true,
87     },
88     ValidTestParam{
89         {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00},
90         false,
91     },
92 
93     // Signed Integer Tests
94     ValidTestParam{
95         {Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE1), 0xFF},
96         static_cast<int8_t>(-1)},
97     ValidTestParam{
98         {Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE2), 0xFF, 0xFF},
99         static_cast<int16_t>(-1)},
100     ValidTestParam{{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE4),
101                     0xFF, 0xFF, 0xFF, 0xFF},
102                    static_cast<int32_t>(-1)},
103     ValidTestParam{{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE8),
104                     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
105                    static_cast<int64_t>(-1)},
106     ValidTestParam{{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE16),
107                     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
108                     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
109                    std::array<uint8_t, 16>{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
110                                            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111                                            0xFF, 0xFF, 0xFF, 0xFF}},
112 
113     // Unsigned Integer Tests
114     ValidTestParam{
115         {Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE1), 0x01},
116         static_cast<uint8_t>(1)},
117     ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE2),
118                     0x00, 0x01},
119                    static_cast<uint16_t>(1)},
120     ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE4),
121                     0x00, 0x00, 0x00, 0x01},
122                    static_cast<uint32_t>(1)},
123     ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE8),
124                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
125                    static_cast<uint64_t>(1)},
126     ValidTestParam{
127         {Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE16), 0x00,
128          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129          0x00, 0x00, 0x01},
130         std::array<uint8_t, 16>{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132                                 0x01}},
133 
134     // UUID Tests
135     ValidTestParam{
136         {Desc(DataElementType::UUID, DataElementSize::BYTE2), 0x01, 0x02},
137         Uuid::From16Bit(0x0102)},
138     ValidTestParam{{Desc(DataElementType::UUID, DataElementSize::BYTE4), 0x01,
139                     0x02, 0x03, 0x04},
140                    Uuid::From32Bit(0x01020304)},
141     ValidTestParam{
142         {Desc(DataElementType::UUID, DataElementSize::BYTE16), 0x00, 0x01, 0x02,
143          0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
144          0x0F},
145         Uuid::From128BitBE({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
146                             0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F})},
147 
148     // String Tests
149     ValidTestParam{
150         {Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_8BIT), 0x05,
151          'T', 'e', 's', 't', '1'},
152         std::string("Test1")},
153     ValidTestParam{
154         {Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_16BIT), 0x00,
155          0x05, 'T', 'e', 's', 't', '2'},
156         std::string("Test2")},
157     ValidTestParam{
158         {Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_32BIT), 0x00,
159          0x00, 0x00, 0x05, 'T', 'e', 's', 't', '3'},
160         std::string("Test3")},
161 
162     // Nested Data Element List Tests
163     ValidTestParam{
164         {Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
165               DataElementSize::ADDITIONAL_8BIT),
166          0x04, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
167          Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00},
168         CreateReader(
169             {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
170              Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00})},
171     ValidTestParam{
172         {Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
173               DataElementSize::ADDITIONAL_16BIT),
174          0x00, 0x04, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1),
175          0x01, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00},
176         CreateReader(
177             {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
178              Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00})},
179     ValidTestParam{
180         {Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
181               DataElementSize::ADDITIONAL_32BIT),
182          0x00, 0x00, 0x00, 0x04,
183          Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
184          Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00},
185         CreateReader(
186             {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
187              Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00})},
188 };
189 
190 INSTANTIATE_TEST_CASE_P(ReadNext, ValidReadTest, ValuesIn(valid_values));
TEST_P(ValidReadTest,Test)191 TEST_P(ValidReadTest, Test) {
192   auto packet = ReaderPacket::Make(std::get<0>(GetParam()));
193   auto value = std::get<1>(GetParam());
194 
195   DataElementReader reader(packet->begin(), packet->end());
196   auto read_value = reader.ReadNext();
197 
198   ASSERT_EQ(value, read_value);
199 
200   // Test that there is no additional data to read.
201   ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
202 }
203 
204 // Test that a nested reader is correctly bounded and can't read past its
205 // defined end.
TEST(ReadNext,BoundedSubreaderTest)206 TEST(ReadNext, BoundedSubreaderTest) {
207   std::vector<uint8_t> payload = {
208       // Subsequence descriptor byte.
209       Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
210            DataElementSize::ADDITIONAL_8BIT),
211       // Subsequence length.
212       0x04,
213       // Subsequence that contains two booleans with values true and false.
214       Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
215       Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00,
216       // Additional int16 at the end of the original sequence.
217       Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE2), 0x01, 0x23};
218 
219   auto packet = ReaderPacket::Make(payload);
220   DataElementReader reader(packet->begin(), packet->end());
221 
222   // The first thing read should be the subsequence.
223   auto data_element = reader.ReadNext();
224   ASSERT_TRUE(std::holds_alternative<DataElementReader>(data_element));
225 
226   // Check that the subsequence matches the premade sequence.
227   auto subreader = std::get<DataElementReader>(data_element);
228   data_element = subreader.ReadNext();
229   ASSERT_TRUE(std::holds_alternative<bool>(data_element));
230   ASSERT_TRUE(std::get<bool>(data_element));
231   data_element = subreader.ReadNext();
232   ASSERT_TRUE(std::holds_alternative<bool>(data_element));
233   ASSERT_FALSE(std::get<bool>(data_element));
234 
235   // Check that there is no additional data to be read from the subreader.
236   ASSERT_EQ(subreader.ReadNext(), DataElement(std::monostate()));
237 
238   // Check that we can still read the int16 from the original reader.
239   data_element = reader.ReadNext();
240   ASSERT_TRUE(std::holds_alternative<int16_t>(data_element));
241   auto int16_value = std::get<int16_t>(data_element);
242   ASSERT_EQ(int16_value, 0x0123);
243 
244   // Check that there is no additional data to be read from the base reader.
245   ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
246 }
247 
248 // Test that trying to read an empty packet fails.
TEST(ReadNext,NoDataTest)249 TEST(ReadNext, NoDataTest) {
250   auto packet = ReaderPacket::Make({});
251   DataElementReader reader(packet->begin(), packet->end());
252 
253   ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
254 }
255 
256 // Test that using a reserved value for type fails.
TEST(ReadNext,InvalidTypeTest)257 TEST(ReadNext, InvalidTypeTest) {
258   auto packet = ReaderPacket::Make({0xFF});
259   DataElementReader reader(packet->begin(), packet->end());
260 
261   ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
262 }
263 
264 // Test all invalid parses due to incorrect lengths or invalid sizes. All tests
265 // should return std::monostate.
266 using InvalidTestParam = std::vector<uint8_t>;
267 class InvalidReadTest : public TestWithParam<InvalidTestParam> {};
268 
269 std::vector<InvalidTestParam> invalid_values = {
270     // Boolean Tests:
271     //   Invalid size field.
272     InvalidTestParam{
273         Desc(DataElementType::BOOLEAN, DataElementSize::BYTE2),
274     },
275     //   Insufficient data.
276     InvalidTestParam{Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1)},
277 
278     // Signed Integer Tests:
279     //   Invalid size field.
280     InvalidTestParam{
281         Desc(DataElementType::SIGNED_INT, DataElementSize::ADDITIONAL_8BIT)},
282     //   1 byte insufficient data.
283     InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE1)},
284     //   2 byte insufficient data.
285     InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE2),
286                      0x00},
287     //   4 byte insufficient data.
288     InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE4),
289                      0x00, 0x00, 0x00},
290     //  8 Byte insufficient data.
291     InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE8),
292                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
293     //  16 Byte insufficient data.
294     InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE16),
295                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296                      0x00, 0x00, 0x00},
297 
298     // Unsigned Integer Tests:
299     //   Invalid size field.
300     InvalidTestParam{
301         Desc(DataElementType::UNSIGNED_INT, DataElementSize::ADDITIONAL_8BIT)},
302     //   1 byte insufficient data.
303     InvalidTestParam{
304         Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE1)},
305     //   2 byte insufficient data.
306     InvalidTestParam{
307         Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE2), 0x00},
308     //   4 byte insufficient data.
309     InvalidTestParam{
310         Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE4), 0x00, 0x00,
311         0x00},
312     //  8 Byte insufficient data.
313     InvalidTestParam{
314         Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE8), 0x00, 0x00,
315         0x00, 0x00, 0x00, 0x00, 0x00},
316     //  16 Byte insufficient data.
317     InvalidTestParam{
318         Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE16), 0x00,
319         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
320 
321     // UUID Tests:
322     //   Invalid size field.
323     InvalidTestParam{
324         Desc(DataElementType::UUID, DataElementSize::ADDITIONAL_8BIT)},
325     //   2 byte insufficient data.
326     InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::BYTE2), 0x00},
327     //   4 byte insufficient data.
328     InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::BYTE4), 0x00,
329                      0x00, 0x00},
330     //  16 Byte insufficient data.
331     InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::BYTE16), 0x00,
332                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333                      0x00, 0x00},
334 
335     // String Tests:
336     //   Invalid size field.
337     InvalidTestParam{Desc(DataElementType::STRING, DataElementSize::BYTE1)},
338     //   Insufficient data for additional 8 bits len.
339     InvalidTestParam{
340         Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_8BIT)},
341     //   Insufficient data for additional 16 bits len.
342     InvalidTestParam{
343         Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_16BIT),
344         0x00,
345     },
346     //   Insufficient data for additional 32 bit len.
347     InvalidTestParam{
348         Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_32BIT),
349         0x00,
350         0x00,
351         0x00,
352     },
353     //   Insufficient data for reported length.
354     InvalidTestParam{
355         Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_8BIT), 0x04,
356         '1', '2', '3'},
357 
358     // Nested Data Element List Tests:
359     //   Invalid size field.
360     InvalidTestParam{
361         Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::BYTE1)},
362     //   Insufficient data for additional 8 bits len.
363     InvalidTestParam{Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
364                           DataElementSize::ADDITIONAL_8BIT)},
365     //   Insufficient data for additional 16 bits len.
366     InvalidTestParam{
367         Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
368              DataElementSize::ADDITIONAL_16BIT),
369         0x00,
370     },
371     //   Insufficient data for additional 32 bit len.
372     InvalidTestParam{
373         Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
374              DataElementSize::ADDITIONAL_32BIT),
375         0x00,
376         0x00,
377         0x00,
378     },
379     //   Insufficient data for reported length.
380     InvalidTestParam{Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
381                           DataElementSize::ADDITIONAL_8BIT),
382                      0x04, 0x00, 0x00, 0x00},
383 
384     // Unhandled Data Element Types Tests:
385     // NOTE: These tests should go away as we begin to handle the types.
386     //   Nil Type.
387     InvalidTestParam{Desc(DataElementType::NIL, DataElementSize::BYTE1)},
388     //   Data Element Alternative List Type.
389     InvalidTestParam{Desc(DataElementType::DATA_ELEMENT_ALTERNATIVE,
390                           DataElementSize::ADDITIONAL_8BIT),
391                      0x00},
392     //   URL Type.
393     InvalidTestParam{
394         Desc(DataElementType::URL, DataElementSize::ADDITIONAL_8BIT), 0x00}};
395 
396 INSTANTIATE_TEST_CASE_P(ReadNext, InvalidReadTest, ValuesIn(invalid_values));
TEST_P(InvalidReadTest,Test)397 TEST_P(InvalidReadTest, Test) {
398   auto packet = ReaderPacket::Make(GetParam());
399   DataElementReader reader(packet->begin(), packet->end());
400 
401   ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
402 }
403 
404 // Test that trying to read from a reader with start > end crashes.
TEST(DataElementReader,BadBoundsDeathTest)405 TEST(DataElementReader, BadBoundsDeathTest) {
406   auto packet = ReaderPacket::Make({0x00, 0x00, 0x00, 0x00});
407   DataElementReader reader(packet->end(), packet->begin());
408   ASSERT_DEATH(reader.ReadNext(), "Beginning of buffer is past end of buffer.");
409 }
410 
411 }  // namespace sdp
412 }  // namespace bluetooth
413