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 <gtest/gtest.h>
20
21 #include <base/logging.h>
22 #include <base/strings/string_number_conversions.h>
23 #include "gatt/database.h"
24 #include "gatt/database_builder.h"
25 #include "stack/include/gattdefs.h"
26
27 using bluetooth::Uuid;
28
29 namespace gatt {
30
31 namespace {
32 const Uuid PRIMARY_SERVICE = Uuid::From16Bit(GATT_UUID_PRI_SERVICE);
33 const Uuid SECONDARY_SERVICE = Uuid::From16Bit(GATT_UUID_SEC_SERVICE);
34 const Uuid INCLUDE = Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE);
35 const Uuid CHARACTERISTIC = Uuid::From16Bit(GATT_UUID_CHAR_DECLARE);
36 const Uuid CHARACTERISTIC_EXTENDED_PROPERTIES =
37 Uuid::From16Bit(GATT_UUID_CHAR_EXT_PROP);
38
39 Uuid SERVICE_1_UUID = Uuid::FromString("1800");
40 Uuid SERVICE_2_UUID = Uuid::FromString("1801");
41 Uuid SERVICE_1_CHAR_1_UUID = Uuid::FromString("2a00");
42 Uuid SERVICE_1_CHAR_1_DESC_1_UUID = Uuid::FromString("2902");
43 } // namespace
44
45 /* This test makes sure that each possible GATT cache element is properly
46 * serialized into StoredAttribute */
TEST(GattDatabaseTest,serialize_deserialize_binary_test)47 TEST(GattDatabaseTest, serialize_deserialize_binary_test) {
48 DatabaseBuilder builder;
49 builder.AddService(0x0001, 0x000f, SERVICE_1_UUID, true);
50 builder.AddService(0x0010, 0x001f, SERVICE_2_UUID, false);
51 builder.AddIncludedService(0x0002, SERVICE_2_UUID, 0x0010, 0x001f);
52 builder.AddCharacteristic(0x0003, 0x0004, SERVICE_1_CHAR_1_UUID, 0x02);
53 builder.AddDescriptor(0x0005, SERVICE_1_CHAR_1_DESC_1_UUID);
54 builder.AddDescriptor(0x0006, CHARACTERISTIC_EXTENDED_PROPERTIES);
55
56 // Set value of only «Characteristic Extended Properties» descriptor
57 builder.SetValueOfDescriptors({0x0001});
58
59 Database db = builder.Build();
60 std::vector<StoredAttribute> serialized = db.Serialize();
61
62 // Primary Service
63 EXPECT_EQ(serialized[0].handle, 0x0001);
64 EXPECT_EQ(serialized[0].type, PRIMARY_SERVICE);
65 EXPECT_EQ(serialized[0].value.service.uuid, SERVICE_1_UUID);
66 EXPECT_EQ(serialized[0].value.service.end_handle, 0x000f);
67
68 // Secondary Service
69 EXPECT_EQ(serialized[1].handle, 0x0010);
70 EXPECT_EQ(serialized[1].type, SECONDARY_SERVICE);
71 EXPECT_EQ(serialized[1].value.service.uuid, SERVICE_2_UUID);
72 EXPECT_EQ(serialized[1].value.service.end_handle, 0x001f);
73
74 // Included Service
75 EXPECT_EQ(serialized[2].handle, 0x0002);
76 EXPECT_EQ(serialized[2].type, INCLUDE);
77 EXPECT_EQ(serialized[2].value.included_service.handle, 0x0010);
78 EXPECT_EQ(serialized[2].value.included_service.end_handle, 0x001f);
79 EXPECT_EQ(serialized[2].value.included_service.uuid, SERVICE_2_UUID);
80
81 // Characteristic
82 EXPECT_EQ(serialized[3].handle, 0x0003);
83 EXPECT_EQ(serialized[3].type, CHARACTERISTIC);
84 EXPECT_EQ(serialized[3].value.characteristic.properties, 0x02);
85 EXPECT_EQ(serialized[3].value.characteristic.value_handle, 0x0004);
86 EXPECT_EQ(serialized[3].value.characteristic.uuid, SERVICE_1_CHAR_1_UUID);
87
88 // Descriptor
89 EXPECT_EQ(serialized[4].handle, 0x0005);
90 EXPECT_EQ(serialized[4].type, SERVICE_1_CHAR_1_DESC_1_UUID);
91
92 // Characteristic Extended Properties Descriptor
93 EXPECT_EQ(serialized[5].handle, 0x0006);
94 EXPECT_EQ(serialized[5].type, CHARACTERISTIC_EXTENDED_PROPERTIES);
95 EXPECT_EQ(serialized[5].value.characteristic_extended_properties, 0x0001);
96 }
97
98 /* This test makes sure that Service represented in StoredAttribute have proper
99 * binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_service_test)100 TEST(GattCacheTest, stored_attribute_to_binary_service_test) {
101 StoredAttribute attr;
102
103 /* make sure padding at end of union is cleared */
104 memset(&attr, 0, sizeof(attr));
105
106 attr = {
107 .handle = 0x0001,
108 .type = PRIMARY_SERVICE,
109 .value = {.service = {.uuid = Uuid::FromString("1800"),
110 .end_handle = 0x001c}},
111 };
112
113 constexpr size_t len = sizeof(StoredAttribute);
114 // clang-format off
115 uint8_t binary_form[len] = {
116 /*handle */ 0x01, 0x00,
117 /* type*/ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
118 /* service uuid */ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
119 /* end handle */ 0x1C, 0x00,
120 /* cleared padding at end of union*/ 0x00, 0x00};
121 // clang-format on
122
123 // useful for debugging:
124 // LOG(ERROR) << " " << base::HexEncode(&attr, len);
125 EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
126 }
127
128 /* This test makes sure that Service represented in StoredAttribute have proper
129 * binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_included_service_test)130 TEST(GattCacheTest, stored_attribute_to_binary_included_service_test) {
131 StoredAttribute attr;
132
133 /* make sure padding at end of union is cleared */
134 memset(&attr, 0, sizeof(attr));
135
136 attr = {
137 .handle = 0x0001,
138 .type = INCLUDE,
139 .value = {.included_service =
140 {
141 .handle = 0x0010,
142 .end_handle = 0x001f,
143 .uuid = Uuid::FromString("1801"),
144 }},
145 };
146
147 constexpr size_t len = sizeof(StoredAttribute);
148 // clang-format off
149 uint8_t binary_form[len] = {
150 /*handle */ 0x01, 0x00,
151 /* type*/ 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
152 /* handle */ 0x10, 0x00,
153 /* end handle */ 0x1f, 0x00,
154 /* service uuid */ 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
155 // clang-format on
156
157 // useful for debugging:
158 // LOG(ERROR) << " " << base::HexEncode(&attr, len);
159 EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
160 }
161
162 /* This test makes sure that «Characteristic Extended Properties» descriptor
163 * represented in StoredAttribute have proper binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_characteristic_test)164 TEST(GattCacheTest, stored_attribute_to_binary_characteristic_test) {
165 StoredAttribute attr;
166
167 /* make sure padding at end of union is cleared */
168 memset(&attr, 0, sizeof(attr));
169
170 attr = {
171 .handle = 0x0002,
172 .type = CHARACTERISTIC,
173 .value = {.characteristic = {.properties = 0x02,
174 .value_handle = 0x0003,
175 .uuid = Uuid::FromString("2a00")}},
176 };
177
178 constexpr size_t len = sizeof(StoredAttribute);
179 // clang-format off
180 uint8_t binary_form[len] = {
181 /*handle */ 0x02, 0x00,
182 /* type */ 0x00, 0x00, 0x28, 0x03, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
183 /* properties */ 0x02,
184 /* after properties there is one byte padding. This might cause troube
185 on other platforms, investigate if it's ever a problem */ 0x00,
186 /* value handle */ 0x03, 0x00,
187 /* uuid */ 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
188 // clang-format on
189
190 // useful for debugging:
191 // LOG(ERROR) << " " << base::HexEncode(&attr, len);
192 EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
193 }
194
195 /* This test makes sure that Descriptor represented in StoredAttribute have
196 * proper binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_descriptor_test)197 TEST(GattCacheTest, stored_attribute_to_binary_descriptor_test) {
198 StoredAttribute attr;
199
200 /* make sure padding at end of union is cleared */
201 memset(&attr, 0, sizeof(attr));
202
203 attr = {.handle = 0x0003, .type = Uuid::FromString("2902"), .value = {}};
204
205 constexpr size_t len = sizeof(StoredAttribute);
206 // clang-format off
207 uint8_t binary_form[len] = {
208 /*handle */ 0x03, 0x00,
209 /* type */ 0x00, 0x00, 0x29, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
210 /* clear padding */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
212 // clang-format on
213
214 // useful for debugging:
215 // LOG(ERROR) << " " << base::HexEncode(&attr, len);
216 EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
217 }
218
219 // Example from Bluetooth SPEC V5.2, Vol 3, Part G, APPENDIX B
TEST(GattDatabaseTest,hash_test)220 TEST(GattDatabaseTest, hash_test) {
221 DatabaseBuilder builder;
222 builder.AddService(0x0001, 0x0005, Uuid::From16Bit(0x1800), true);
223 builder.AddService(0x0006, 0x000D, Uuid::From16Bit(0x1801), true);
224 builder.AddService(0x000E, 0x0013, Uuid::From16Bit(0x1808), true);
225 builder.AddService(0x0014, 0xFFFF, Uuid::From16Bit(0x180F), false);
226
227 builder.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2A00), 0x0A);
228 builder.AddCharacteristic(0x0004, 0x0005, Uuid::From16Bit(0x2A01), 0x02);
229
230 builder.AddCharacteristic(0x0007, 0x0008, Uuid::From16Bit(0x2A05), 0x20);
231 builder.AddDescriptor(0x0009, Uuid::From16Bit(0x2902));
232 builder.AddCharacteristic(0x000A, 0x000B, Uuid::From16Bit(0x2B29), 0x0A);
233 builder.AddCharacteristic(0x000C, 0x000D, Uuid::From16Bit(0x2B2A), 0x02);
234
235 builder.AddIncludedService(0x000F, Uuid::From16Bit(0x180F), 0x0014, 0x0016);
236 builder.AddCharacteristic(0x0010, 0x0011, Uuid::From16Bit(0x2A18), 0xA2);
237 builder.AddDescriptor(0x0012, Uuid::From16Bit(0x2902));
238 builder.AddDescriptor(0x0013, Uuid::From16Bit(0x2900));
239
240 builder.AddCharacteristic(0x0015, 0x0016, Uuid::From16Bit(0x2A19), 0x02);
241
242 // set characteristic extended properties descriptor values
243 std::vector<uint16_t> descriptorValues = {0x0000};
244 builder.SetValueOfDescriptors(descriptorValues);
245
246 Database db = builder.Build();
247
248 // Big endian example from Bluetooth SPEC V5.2, Vol 3, Part G, APPENDIX B
249 Octet16 expected_hash{0xF1, 0xCA, 0x2D, 0x48, 0xEC, 0xF5, 0x8B, 0xAC,
250 0x8A, 0x88, 0x30, 0xBB, 0xB9, 0xFB, 0xA9, 0x90};
251
252 Octet16 hash = db.Hash();
253 // Convert output hash from little endian to big endian
254 std::reverse(hash.begin(), hash.end());
255
256 EXPECT_EQ(hash, expected_hash);
257 }
258
259 /* This test makes sure that Descriptor represented in StoredAttribute have
260 * proper binary format. */
TEST(GattCacheTest,stored_attribute_to_binary_characteristic_extended_properties_test)261 TEST(GattCacheTest,
262 stored_attribute_to_binary_characteristic_extended_properties_test) {
263 StoredAttribute attr;
264
265 /* make sure padding at end of union is cleared */
266 memset(&attr, 0, sizeof(attr));
267
268 attr = {.handle = 0x0003,
269 .type = Uuid::FromString("2900"),
270 .value = {.characteristic_extended_properties = 0x0001}};
271
272 constexpr size_t len = sizeof(StoredAttribute);
273 // clang-format off
274 uint8_t binary_form[len] = {
275 /*handle */ 0x03, 0x00,
276 /* type */ 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
277 /* characteristic extended properties */ 0x01, 0x00,
278 /* clear padding */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 0x00, 0x00, 0x00, 0x00};
280 // clang-format on
281
282 // useful for debugging:
283 // LOG(ERROR) << " " << base::HexEncode(&attr, len);
284 EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
285 }
286 } // namespace gatt
287