1 /******************************************************************************
2  *
3  *  Copyright 2018 The Android Open Source Project
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #include "gatt/database.h"
20 
21 #include <base/strings/string_number_conversions.h>
22 #include <bluetooth/log.h>
23 #include <gtest/gtest.h>
24 
25 #include "gatt/database_builder.h"
26 #include "stack/include/gattdefs.h"
27 #include "types/bluetooth/uuid.h"
28 
29 using bluetooth::Uuid;
30 using namespace bluetooth;
31 
32 namespace gatt {
33 
34 namespace {
35 const Uuid PRIMARY_SERVICE = Uuid::From16Bit(GATT_UUID_PRI_SERVICE);
36 const Uuid SECONDARY_SERVICE = Uuid::From16Bit(GATT_UUID_SEC_SERVICE);
37 const Uuid INCLUDE = Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE);
38 const Uuid CHARACTERISTIC = Uuid::From16Bit(GATT_UUID_CHAR_DECLARE);
39 const Uuid CHARACTERISTIC_EXTENDED_PROPERTIES = Uuid::From16Bit(GATT_UUID_CHAR_EXT_PROP);
40 
41 Uuid SERVICE_1_UUID = Uuid::FromString("1800");
42 Uuid SERVICE_2_UUID = Uuid::FromString("1801");
43 Uuid SERVICE_1_CHAR_1_UUID = Uuid::FromString("2a00");
44 Uuid SERVICE_1_CHAR_1_DESC_1_UUID = Uuid::FromString("2902");
45 }  // namespace
46 
47 /* This test makes sure that each possible GATT cache element is properly
48  * serialized into StoredAttribute */
TEST(GattDatabaseTest,serialize_deserialize_binary_test)49 TEST(GattDatabaseTest, serialize_deserialize_binary_test) {
50   DatabaseBuilder builder;
51   builder.AddService(0x0001, 0x000f, SERVICE_1_UUID, true);
52   builder.AddService(0x0010, 0x001f, SERVICE_2_UUID, false);
53   builder.AddIncludedService(0x0002, SERVICE_2_UUID, 0x0010, 0x001f);
54   builder.AddCharacteristic(0x0003, 0x0004, SERVICE_1_CHAR_1_UUID, 0x02);
55   builder.AddDescriptor(0x0005, SERVICE_1_CHAR_1_DESC_1_UUID);
56   builder.AddDescriptor(0x0006, CHARACTERISTIC_EXTENDED_PROPERTIES);
57 
58   // Set value of only «Characteristic Extended Properties» descriptor
59   builder.SetValueOfDescriptors({0x0001});
60 
61   Database db = builder.Build();
62   std::vector<StoredAttribute> serialized = db.Serialize();
63 
64   // Primary Service
65   EXPECT_EQ(serialized[0].handle, 0x0001);
66   EXPECT_EQ(serialized[0].type, PRIMARY_SERVICE);
67   EXPECT_EQ(serialized[0].value.service.uuid, SERVICE_1_UUID);
68   EXPECT_EQ(serialized[0].value.service.end_handle, 0x000f);
69 
70   // Secondary Service
71   EXPECT_EQ(serialized[1].handle, 0x0010);
72   EXPECT_EQ(serialized[1].type, SECONDARY_SERVICE);
73   EXPECT_EQ(serialized[1].value.service.uuid, SERVICE_2_UUID);
74   EXPECT_EQ(serialized[1].value.service.end_handle, 0x001f);
75 
76   // Included Service
77   EXPECT_EQ(serialized[2].handle, 0x0002);
78   EXPECT_EQ(serialized[2].type, INCLUDE);
79   EXPECT_EQ(serialized[2].value.included_service.handle, 0x0010);
80   EXPECT_EQ(serialized[2].value.included_service.end_handle, 0x001f);
81   EXPECT_EQ(serialized[2].value.included_service.uuid, SERVICE_2_UUID);
82 
83   // Characteristic
84   EXPECT_EQ(serialized[3].handle, 0x0003);
85   EXPECT_EQ(serialized[3].type, CHARACTERISTIC);
86   EXPECT_EQ(serialized[3].value.characteristic.properties, 0x02);
87   EXPECT_EQ(serialized[3].value.characteristic.value_handle, 0x0004);
88   EXPECT_EQ(serialized[3].value.characteristic.uuid, SERVICE_1_CHAR_1_UUID);
89 
90   // Descriptor
91   EXPECT_EQ(serialized[4].handle, 0x0005);
92   EXPECT_EQ(serialized[4].type, SERVICE_1_CHAR_1_DESC_1_UUID);
93 
94   // Characteristic Extended Properties Descriptor
95   EXPECT_EQ(serialized[5].handle, 0x0006);
96   EXPECT_EQ(serialized[5].type, CHARACTERISTIC_EXTENDED_PROPERTIES);
97   EXPECT_EQ(serialized[5].value.characteristic_extended_properties, 0x0001);
98 }
99 
100 /* This test makes sure that Service represented in StoredAttribute have proper
101  * binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_service_test)102 TEST(GattCacheTest, stored_attribute_to_binary_service_test) {
103   StoredAttribute attr;
104 
105   /* make sure padding at end of union is cleared */
106   memset(&attr, 0, sizeof(attr));
107 
108   attr = {
109           .handle = 0x0001,
110           .type = PRIMARY_SERVICE,
111           .value = {.service = {.uuid = Uuid::FromString("1800"), .end_handle = 0x001c}},
112   };
113 
114   constexpr size_t len = sizeof(StoredAttribute);
115   // clang-format off
116   uint8_t binary_form[len] = {
117       /*handle */ 0x01, 0x00,
118       /* type*/ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
119       /* service uuid */ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
120       /* end handle */ 0x1C, 0x00,
121       /* padding at end of union*/ 0x00, 0x00};
122   // clang-format on
123 
124   // useful for debugging:
125   // log::error("{}", base::HexEncode(&attr, len));
126 
127   // Do not compare last 2 bytes which are padding as
128   // x86 can use non-zero padding causing the test to fail
129   EXPECT_EQ(memcmp(binary_form, &attr, len - 2), 0);
130 }
131 
132 /* This test makes sure that Service represented in StoredAttribute have proper
133  * binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_included_service_test)134 TEST(GattCacheTest, stored_attribute_to_binary_included_service_test) {
135   StoredAttribute attr;
136 
137   /* make sure padding at end of union is cleared */
138   memset(&attr, 0, sizeof(attr));
139 
140   attr = {
141           .handle = 0x0001,
142           .type = INCLUDE,
143           .value = {.included_service =
144                             {
145                                     .handle = 0x0010,
146                                     .end_handle = 0x001f,
147                                     .uuid = Uuid::FromString("1801"),
148                             }},
149   };
150 
151   constexpr size_t len = sizeof(StoredAttribute);
152   // clang-format off
153   uint8_t binary_form[len] = {
154       /*handle */ 0x01, 0x00,
155       /* type*/ 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
156       /* handle */ 0x10, 0x00,
157       /* end handle */ 0x1f, 0x00,
158       /* service uuid */ 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
159   // clang-format on
160 
161   // useful for debugging:
162   // log::error("{}", base::HexEncode(&attr, len));
163   EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
164 }
165 
166 /* This test makes sure that «Characteristic Extended Properties» descriptor
167  * represented in StoredAttribute have proper binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_characteristic_test)168 TEST(GattCacheTest, stored_attribute_to_binary_characteristic_test) {
169   StoredAttribute attr;
170 
171   /* make sure padding at end of union is cleared */
172   memset(&attr, 0, sizeof(attr));
173 
174   attr = {
175           .handle = 0x0002,
176           .type = CHARACTERISTIC,
177           .value = {.characteristic = {.properties = 0x02,
178                                        .value_handle = 0x0003,
179                                        .uuid = Uuid::FromString("2a00")}},
180   };
181 
182   constexpr size_t len = sizeof(StoredAttribute);
183   // clang-format off
184   uint8_t binary_form[len] = {
185       /*handle */ 0x02, 0x00,
186       /* type */ 0x00, 0x00, 0x28, 0x03, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
187       /* properties */ 0x02,
188       /* after properties there is one byte padding. This might cause troube
189          on other platforms, investigate if it's ever a problem */ 0x00,
190       /* value handle */ 0x03, 0x00,
191       /* uuid */ 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
192   // clang-format on
193 
194   // useful for debugging:
195   // log::error("{}", base::HexEncode(&attr, len));
196   EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
197 }
198 
199 /* This test makes sure that Descriptor represented in StoredAttribute have
200  * proper binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_descriptor_test)201 TEST(GattCacheTest, stored_attribute_to_binary_descriptor_test) {
202   StoredAttribute attr;
203 
204   /* make sure padding at end of union is cleared */
205   memset(&attr, 0, sizeof(attr));
206 
207   attr = {.handle = 0x0003,
208           .type = Uuid::FromString("2902"),
209           .value = {.characteristic_extended_properties = 0x00}};
210 
211   constexpr size_t len = sizeof(StoredAttribute);
212   // clang-format off
213   uint8_t binary_form[len] = {
214       /*handle */ 0x03, 0x00,
215       /* type */ 0x00, 0x00, 0x29, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
216       /* clear padding    */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217                              0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
218   // clang-format on
219 
220   // useful for debugging:
221   // log::error("{}", base::HexEncode(&attr, len));
222   EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
223 }
224 
225 // Example from Bluetooth SPEC V5.2, Vol 3, Part G, APPENDIX B
TEST(GattDatabaseTest,hash_test)226 TEST(GattDatabaseTest, hash_test) {
227   DatabaseBuilder builder;
228   builder.AddService(0x0001, 0x0005, Uuid::From16Bit(0x1800), true);
229   builder.AddService(0x0006, 0x000D, Uuid::From16Bit(0x1801), true);
230   builder.AddService(0x000E, 0x0013, Uuid::From16Bit(0x1808), true);
231   builder.AddService(0x0014, 0xFFFF, Uuid::From16Bit(0x180F), false);
232 
233   builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2A00), 0x0A);
234   builder.AddCharacteristic(0x0004, 0x0005, Uuid::From16Bit(0x2A01), 0x02);
235 
236   builder.AddCharacteristic(0x0007, 0x0008, Uuid::From16Bit(0x2A05), 0x20);
237   builder.AddDescriptor(0x0009, Uuid::From16Bit(0x2902));
238   builder.AddCharacteristic(0x000A, 0x000B, Uuid::From16Bit(0x2B29), 0x0A);
239   builder.AddCharacteristic(0x000C, 0x000D, Uuid::From16Bit(0x2B2A), 0x02);
240 
241   builder.AddIncludedService(0x000F, Uuid::From16Bit(0x180F), 0x0014, 0x0016);
242   builder.AddCharacteristic(0x0010, 0x0011, Uuid::From16Bit(0x2A18), 0xA2);
243   builder.AddDescriptor(0x0012, Uuid::From16Bit(0x2902));
244   builder.AddDescriptor(0x0013, Uuid::From16Bit(0x2900));
245 
246   builder.AddCharacteristic(0x0015, 0x0016, Uuid::From16Bit(0x2A19), 0x02);
247 
248   // set characteristic extended properties descriptor values
249   std::vector<uint16_t> descriptorValues = {0x0000};
250   builder.SetValueOfDescriptors(descriptorValues);
251 
252   Database db = builder.Build();
253 
254   // Big endian example from Bluetooth SPEC V5.2, Vol 3, Part G, APPENDIX B
255   Octet16 expected_hash{0xF1, 0xCA, 0x2D, 0x48, 0xEC, 0xF5, 0x8B, 0xAC,
256                         0x8A, 0x88, 0x30, 0xBB, 0xB9, 0xFB, 0xA9, 0x90};
257 
258   Octet16 hash = db.Hash();
259   // Convert output hash from little endian to big endian
260   std::reverse(hash.begin(), hash.end());
261 
262   EXPECT_EQ(hash, expected_hash);
263 }
264 
265 /* This test makes sure that Descriptor represented in StoredAttribute have
266  * proper binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_characteristic_extended_properties_test)267 TEST(GattCacheTest, stored_attribute_to_binary_characteristic_extended_properties_test) {
268   StoredAttribute attr;
269 
270   /* make sure padding at end of union is cleared */
271   memset(&attr, 0, sizeof(attr));
272 
273   attr = {.handle = 0x0003,
274           .type = Uuid::FromString("2900"),
275           .value = {.characteristic_extended_properties = 0x0001}};
276 
277   constexpr size_t len = sizeof(StoredAttribute);
278   // clang-format off
279   std::vector<uint8_t> binary_form {
280       /*handle */ 0x03, 0x00,
281       /* type */ 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
282       /* characteristic extended properties */ 0x01, 0x00,
283       /* clear padding    */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284                              0x00, 0x00, 0x00, 0x00};
285   // clang-format on
286 
287   // useful for debugging:
288   // log::error("{}", base::HexEncode(&attr, len));
289   EXPECT_EQ(memcmp(binary_form.data(), &attr, len), 0);
290 
291   // Don't use memcmp, for better error messages.
292   std::vector<uint8_t> copied(len, 0);
293   memcpy(copied.data(), &attr, StoredAttribute::kSizeOnDisk);
294 
295   EXPECT_EQ(binary_form, copied);
296 }
297 
298 /* This test makes sure that Descriptor represented in StoredAttribute have
299  * proper binary format. */
TEST(GattCacheTest,stored_attribute_serialized_to_binary_characteristic_extended_properties_test)300 TEST(GattCacheTest, stored_attribute_serialized_to_binary_characteristic_extended_properties_test) {
301   StoredAttribute attr;
302 
303   attr = {.handle = 0x0003,
304           .type = Uuid::FromString("2900"),
305           .value = {.characteristic_extended_properties = 0x0001}};
306 
307   constexpr size_t len = StoredAttribute::kSizeOnDisk;
308   std::vector<uint8_t> serialized;
309   StoredAttribute::SerializeStoredAttribute(attr, serialized);
310 
311   // clang-format off
312   std::vector<uint8_t> binary_form {
313       /*handle */ 0x03, 0x00,
314       /* type */ 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
315       /* characteristic extended properties */ 0x01, 0x00,
316       /* clear padding    */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317                              0x00, 0x00, 0x00, 0x00};
318   // clang-format on
319 
320   EXPECT_EQ(binary_form.size(), len);
321   EXPECT_EQ(binary_form.size(), serialized.size());
322   EXPECT_EQ(binary_form, serialized);
323 }
324 
325 /* This test makes sure that Descriptor represented in StoredAttribute have
326  * proper binary format. */
TEST(GattCacheTest,stored_attributes_serialized_to_binary_test)327 TEST(GattCacheTest, stored_attributes_serialized_to_binary_test) {
328   // Allocate enough space so that no matter the layout, we don't overflow.
329   uint8_t attr_bytes[StoredAttribute::kSizeOnDisk * 2];
330   // This is the attribute we fill from a binary representation
331   StoredAttribute attr;
332 
333   /*
334   // Characteristic extended property
335   attr = {.handle = 0x0003,
336           .type = Uuid::FromString("2900"),
337           .value.characteristic_extended_properties = 0x1234};
338   log::error("{}", base::HexEncode(&attr, StoredAttribute::kSizeOnDisk));
339   */
340 
341   memcpy(attr_bytes,
342          "\x03\x00"                                                          // handle
343          "\x00\x00\x29\x00\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB"  // Uuid
344          "\x34\x12"                                                          // extended property
345          "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
346          "\x00",
347          StoredAttribute::kSizeOnDisk);
348   attr = *(StoredAttribute*)attr_bytes;
349 
350   std::vector<uint8_t> serialized;
351   StoredAttribute::SerializeStoredAttribute(attr, serialized);
352   std::vector<uint8_t> copied(StoredAttribute::kSizeOnDisk, 0);
353   memcpy(copied.data(), &attr, StoredAttribute::kSizeOnDisk);
354 
355   EXPECT_EQ(serialized, copied);
356   serialized.clear();
357   copied = std::vector<uint8_t>(StoredAttribute::kSizeOnDisk, 0);
358   /*
359   // Primary Service
360   attr = {
361       .handle = 0x0203,
362       .type = Uuid::FromString("2800"),
363       .value.service =
364           {
365               .uuid = Uuid::FromString("4203"),
366               .end_handle = 0x1203,
367           },
368   };
369   log::error("{}", base::HexEncode(&attr, StoredAttribute::kSizeOnDisk));
370   */
371   memcpy(attr_bytes,
372          "\x03\x02"                                                          // handle
373          "\x00\x00\x28\x00\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB"  // Type
374          "\x00\x00\x42\x03\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB"  // Uuid
375          "\x03\x12"                                                          // end_handle
376          "\x00\x00",
377          StoredAttribute::kSizeOnDisk);
378   attr = *(StoredAttribute*)attr_bytes;
379 
380   StoredAttribute::SerializeStoredAttribute(attr, serialized);
381   memcpy(copied.data(), &attr, StoredAttribute::kSizeOnDisk);
382   EXPECT_EQ(serialized, copied);
383   serialized.clear();
384   copied = std::vector<uint8_t>(StoredAttribute::kSizeOnDisk, 0);
385 
386   /*
387   // Secondary Service
388   attr = {
389       .handle = 0x0304,
390       .type = Uuid::FromString("2801"),
391       .value.service =
392           {
393               .uuid = Uuid::FromString("4303"),
394               .end_handle = 0x1203,
395           },
396   };
397 
398   log::error("{}", base::HexEncode(&attr, StoredAttribute::kSizeOnDisk));
399   */
400   memcpy(attr_bytes,
401          "\x04\x03"                                                          // handle
402          "\x00\x00\x28\x01\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB"  // type
403          "\x00\x00\x43\x03\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB"  // UUID
404          "\x03\x12"                                                          // end_handle
405          "\x00\x000",
406          StoredAttribute::kSizeOnDisk);
407   attr = *(StoredAttribute*)attr_bytes;
408 
409   StoredAttribute::SerializeStoredAttribute(attr, serialized);
410   memcpy(copied.data(), &attr, StoredAttribute::kSizeOnDisk);
411   EXPECT_EQ(serialized, copied);
412   serialized.clear();
413   copied = std::vector<uint8_t>(StoredAttribute::kSizeOnDisk, 0);
414 
415   /*
416   // Included Service
417   attr = {
418       .handle = 0x0103,
419       .type = Uuid::FromString("2802"),
420       .value.included_service =
421           {
422               .handle = 0x0134,
423               .end_handle = 0x0138,
424               .uuid = Uuid::FromString("3456"),
425           },
426   };
427   log::error("{}", base::HexEncode(&attr, StoredAttribute::kSizeOnDisk));
428   */
429 
430   memcpy(attr_bytes,
431          "\x03\x01"                                                           // handle
432          "\x00\x00\x28\x02\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB"   // type
433          "\x34\x01"                                                           // handle
434          "\x38\x01"                                                           // end_handle
435          "\x00\x00\x34\x56\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB",  // Uuid
436          StoredAttribute::kSizeOnDisk);
437   attr = *(StoredAttribute*)attr_bytes;
438 
439   StoredAttribute::SerializeStoredAttribute(attr, serialized);
440   memcpy(copied.data(), &attr, StoredAttribute::kSizeOnDisk);
441   EXPECT_EQ(serialized, copied);
442   serialized.clear();
443   copied = std::vector<uint8_t>(StoredAttribute::kSizeOnDisk, 0);
444 
445   /*
446   // characteristic definition
447   attr = {
448       .handle = 0x0103,
449       .type = Uuid::FromString("2803"),
450       .value.characteristic = {.properties = 4,
451                                .value_handle = 0x302,
452                                .uuid = Uuid::FromString("3456")},
453   };
454   log::error("{}", base::HexEncode(&attr, StoredAttribute::kSizeOnDisk));
455   */
456   memcpy(attr_bytes,
457          "\x03\x01"                                                           // handle
458          "\x00\x00\x28\x03\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB"   // type
459          "\x04"                                                               // properties
460          "\x00"                                                               // padding
461          "\x02\x03"                                                           // value_handle
462          "\x00\x00\x34\x56\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB",  // uuid
463          StoredAttribute::kSizeOnDisk);
464   attr = *(StoredAttribute*)attr_bytes;
465 
466   StoredAttribute::SerializeStoredAttribute(attr, serialized);
467   memcpy(copied.data(), &attr, StoredAttribute::kSizeOnDisk);
468   EXPECT_EQ(serialized, copied);
469   serialized.clear();
470   copied = std::vector<uint8_t>(StoredAttribute::kSizeOnDisk, 0);
471 
472   /*
473   // Unknown Uuid
474   attr = {
475       .handle = 0x0103,
476       .type = Uuid::FromString("4444"),
477       .value.characteristic = {},
478   };
479   log::error("{}", base::HexEncode(&attr, StoredAttribute::kSizeOnDisk));
480   */
481   memcpy(attr_bytes,
482          "\x03\x01"                                                          // handle
483          "\x00\x00\x44\x44\x00\x00\x10\x00\x80\x00\x00\x80\x5F\x9B\x34\xFB"  // type
484          "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
485          "\x00\x00",
486          StoredAttribute::kSizeOnDisk);
487   attr = *(StoredAttribute*)attr_bytes;
488 
489   StoredAttribute::SerializeStoredAttribute(attr, serialized);
490   memcpy(copied.data(), &attr, StoredAttribute::kSizeOnDisk);
491 
492   EXPECT_EQ(serialized, copied);
493   serialized.clear();
494   copied = std::vector<uint8_t>(StoredAttribute::kSizeOnDisk, 0);
495 }
496 
497 // Example from Bluetooth SPEC V5.2, Vol 3, Part G, APPENDIX B
TEST(GattDatabaseTest,serialized_hash_test)498 TEST(GattDatabaseTest, serialized_hash_test) {
499   DatabaseBuilder builder;
500   builder.AddService(0x0001, 0x0005, Uuid::From16Bit(0x1800), true);
501   builder.AddService(0x0006, 0x000D, Uuid::From16Bit(0x1801), true);
502   builder.AddService(0x000E, 0x0013, Uuid::From16Bit(0x1808), true);
503   builder.AddService(0x0014, 0xFFFF, Uuid::From16Bit(0x180F), false);
504 
505   builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2A00), 0x0A);
506   builder.AddCharacteristic(0x0004, 0x0005, Uuid::From16Bit(0x2A01), 0x02);
507 
508   builder.AddCharacteristic(0x0007, 0x0008, Uuid::From16Bit(0x2A05), 0x20);
509   builder.AddDescriptor(0x0009, Uuid::From16Bit(0x2902));
510   builder.AddCharacteristic(0x000A, 0x000B, Uuid::From16Bit(0x2B29), 0x0A);
511   builder.AddCharacteristic(0x000C, 0x000D, Uuid::From16Bit(0x2B2A), 0x02);
512 
513   builder.AddIncludedService(0x000F, Uuid::From16Bit(0x180F), 0x0014, 0x0016);
514   builder.AddCharacteristic(0x0010, 0x0011, Uuid::From16Bit(0x2A18), 0xA2);
515   builder.AddDescriptor(0x0012, Uuid::From16Bit(0x2902));
516   builder.AddDescriptor(0x0013, Uuid::From16Bit(0x2900));
517 
518   builder.AddCharacteristic(0x0015, 0x0016, Uuid::From16Bit(0x2A19), 0x02);
519 
520   // set characteristic extended properties descriptor values
521   std::vector<uint16_t> descriptorValues = {0x0000};
522   builder.SetValueOfDescriptors(descriptorValues);
523 
524   Database db = builder.Build();
525 
526   auto serialized = db.Serialize();
527   std::vector<uint8_t> bytes;
528   for (auto attr : serialized) {
529     StoredAttribute::SerializeStoredAttribute(attr, bytes);
530   }
531   std::vector<StoredAttribute> attr_from_disk(serialized.size());
532   std::copy(bytes.cbegin(), bytes.cend(), (uint8_t*)attr_from_disk.data());
533   bool is_successful = false;
534   Database db_from_disk = gatt::Database::Deserialize(attr_from_disk, &is_successful);
535   ASSERT_TRUE(is_successful);
536   is_successful = false;
537   Database db_from_serialized = gatt::Database::Deserialize(serialized, &is_successful);
538   ASSERT_TRUE(is_successful);
539 
540   EXPECT_EQ(db_from_disk.Hash(), db_from_serialized.Hash());
541 }
542 }  // namespace gatt
543