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