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