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