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