• Home
  • 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 <base/logging.h>
20 #include <gtest/gtest.h>
21 
22 #include <iterator>
23 #include <utility>
24 
25 #include "gatt/database_builder.h"
26 #include "types/bluetooth/uuid.h"
27 
28 using bluetooth::Uuid;
29 
30 namespace gatt {
31 
32 namespace {
33 /* EXPECT_EQ doesn't work well with static constexpr fields, need a variable
34  * with address */
35 constexpr std::pair<uint16_t, uint16_t> EXPLORE_END =
36     DatabaseBuilder::EXPLORE_END;
37 
38 /* make_pair doesn't work well with EXPECT_EQ, have own helper instead */
make_pair_u16(uint16_t first,uint16_t second)39 inline std::pair<uint16_t, uint16_t> make_pair_u16(uint16_t first,
40                                                    uint16_t second) {
41   return std::make_pair(first, second);
42 }
43 
44 // clang-format off
45 Uuid SERVICE_1_UUID = Uuid::FromString("00001800-0000-1000-8000-00805f9b34fb");
46 Uuid SERVICE_2_UUID = Uuid::FromString("00001801-0000-1000-8000-00805f9b34fb");
47 Uuid SERVICE_3_UUID = Uuid::FromString("0000180f-0000-1000-8000-00805f9b34fb");
48 Uuid SERVICE_4_UUID = Uuid::FromString("0000fef5-0000-1000-8000-00805f9b34fb");
49 Uuid SERVICE_5_UUID = Uuid::FromString("0000180a-0000-1000-8000-00805f9b34fb");
50 Uuid SERVICE_6_UUID = Uuid::FromString("0000fe55-0000-1000-8000-00805f9b34fb");
51 
52 Uuid SERVICE_1_CHAR_1_UUID = Uuid::FromString("00002a00-0000-1000-8000-00805f9b34fb");
53 Uuid SERVICE_1_CHAR_2_UUID = Uuid::FromString("00002a01-0000-1000-8000-00805f9b34fb");
54 Uuid SERVICE_1_CHAR_3_UUID = Uuid::FromString("00002a04-0000-1000-8000-00805f9b34fb");
55 
56 Uuid SERVICE_3_CHAR_1_UUID = Uuid::FromString("00002a19-0000-1000-8000-00805f9b34fb");
57 Uuid SERVICE_3_CHAR_1_DESC_1_UUID = Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb");
58 
59 Uuid SERVICE_4_CHAR_1_UUID = Uuid::FromString("8082caa8-41a6-4021-91c6-56f9b954cc34");
60 Uuid SERVICE_4_CHAR_2_UUID = Uuid::FromString("724249f0-5ec3-4b5f-8804-42345af08651");
61 Uuid SERVICE_4_CHAR_3_UUID = Uuid::FromString("6c53db25-47a1-45fe-a022-7c92fb334fd4");
62 Uuid SERVICE_4_CHAR_4_UUID = Uuid::FromString("9d84b9a3-000c-49d8-9183-855b673fda31");
63 Uuid SERVICE_4_CHAR_5_UUID = Uuid::FromString("457871e8-d516-4ca1-9116-57d0b17b9cb2");
64 Uuid SERVICE_4_CHAR_6_UUID = Uuid::FromString("5f78df94-798c-46f5-990a-b3eb6a065c88");
65 Uuid SERVICE_4_CHAR_6_DESC_1_UUID = Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb");
66 
67 Uuid SERVICE_5_CHAR_1_UUID = Uuid::FromString("00002a29-0000-1000-8000-00805f9b34fb");
68 Uuid SERVICE_5_CHAR_2_UUID = Uuid::FromString("00002a24-0000-1000-8000-00805f9b34fb");
69 Uuid SERVICE_5_CHAR_3_UUID = Uuid::FromString("00002a25-0000-1000-8000-00805f9b34fb");
70 Uuid SERVICE_5_CHAR_4_UUID = Uuid::FromString("00002a27-0000-1000-8000-00805f9b34fb");
71 Uuid SERVICE_5_CHAR_5_UUID = Uuid::FromString("00002a26-0000-1000-8000-00805f9b34fb");
72 Uuid SERVICE_5_CHAR_6_UUID = Uuid::FromString("00002a28-0000-1000-8000-00805f9b34fb");
73 Uuid SERVICE_5_CHAR_7_UUID = Uuid::FromString("00002a50-0000-1000-8000-00805f9b34fb");
74 
75 Uuid SERVICE_6_CHAR_1_UUID = Uuid::FromString("00000001-1000-1000-8000-00805f9b34fb");
76 Uuid SERVICE_6_CHAR_1_DESC_1_UUID = Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb");
77 Uuid SERVICE_6_CHAR_2_UUID = Uuid::FromString("00000002-1000-1000-8000-00805f9b34fb");
78 Uuid SERVICE_6_CHAR_3_UUID = Uuid::FromString("00000003-1000-1000-8000-00805f9b34fb");
79 // clang-format on
80 
81 }  // namespace
82 
83 // clang-format off
84 /* Content of sample database, comes from Daydream controller:
85 Service: handle=0x0001, end_handle=0x0007, uuid=00001800-0000-1000-8000-00805f9b34fb
86 	 Characteristic: declaration_handle=0x0002, value_handle=0x0003, uuid=00002a00-0000-1000-8000-00805f9b34fb, prop=0x02
87 	 Characteristic: declaration_handle=0x0004, value_handle=0x0005, uuid=00002a01-0000-1000-8000-00805f9b34fb, prop=0x02
88 	 Characteristic: declaration_handle=0x0006, value_handle=0x0007, uuid=00002a04-0000-1000-8000-00805f9b34fb, prop=0x02
89 Service: handle=0x0008, end_handle=0x0008, uuid=00001801-0000-1000-8000-00805f9b34fb
90 Service: handle=0x0009, end_handle=0x000c, uuid=0000180f-0000-1000-8000-00805f9b34fb
91 	 Characteristic: declaration_handle=0x000a, value_handle=0x000b, uuid=00002a19-0000-1000-8000-00805f9b34fb, prop=0x12
92 		 Descriptor: handle=0x000c, uuid=00002902-0000-1000-8000-00805f9b34fb
93 Service: handle=0x000d, end_handle=0x001a, uuid=0000fef5-0000-1000-8000-00805f9b34fb
94 	 Characteristic: declaration_handle=0x000e, value_handle=0x000f, uuid=8082caa8-41a6-4021-91c6-56f9b954cc34, prop=0x0a
95 	 Characteristic: declaration_handle=0x0010, value_handle=0x0011, uuid=724249f0-5ec3-4b5f-8804-42345af08651, prop=0x0a
96 	 Characteristic: declaration_handle=0x0012, value_handle=0x0013, uuid=6c53db25-47a1-45fe-a022-7c92fb334fd4, prop=0x02
97 	 Characteristic: declaration_handle=0x0014, value_handle=0x0015, uuid=9d84b9a3-000c-49d8-9183-855b673fda31, prop=0x0a
98 	 Characteristic: declaration_handle=0x0016, value_handle=0x0017, uuid=457871e8-d516-4ca1-9116-57d0b17b9cb2, prop=0x0e
99 	 Characteristic: declaration_handle=0x0018, value_handle=0x0019, uuid=5f78df94-798c-46f5-990a-b3eb6a065c88, prop=0x12
100 		 Descriptor: handle=0x001a, uuid=00002902-0000-1000-8000-00805f9b34fb
101 Service: handle=0x001b, end_handle=0x0029, uuid=0000180a-0000-1000-8000-00805f9b34fb
102 	 Characteristic: declaration_handle=0x001c, value_handle=0x001d, uuid=00002a29-0000-1000-8000-00805f9b34fb, prop=0x02
103 	 Characteristic: declaration_handle=0x001e, value_handle=0x001f, uuid=00002a24-0000-1000-8000-00805f9b34fb, prop=0x02
104 	 Characteristic: declaration_handle=0x0020, value_handle=0x0021, uuid=00002a25-0000-1000-8000-00805f9b34fb, prop=0x02
105 	 Characteristic: declaration_handle=0x0022, value_handle=0x0023, uuid=00002a27-0000-1000-8000-00805f9b34fb, prop=0x02
106 	 Characteristic: declaration_handle=0x0024, value_handle=0x0025, uuid=00002a26-0000-1000-8000-00805f9b34fb, prop=0x02
107 	 Characteristic: declaration_handle=0x0026, value_handle=0x0027, uuid=00002a28-0000-1000-8000-00805f9b34fb, prop=0x02
108 	 Characteristic: declaration_handle=0x0028, value_handle=0x0029, uuid=00002a50-0000-1000-8000-00805f9b34fb, prop=0x02
109 Service: handle=0x002a, end_handle=0x0031, uuid=0000fe55-0000-1000-8000-00805f9b34fb
110 	 Characteristic: declaration_handle=0x002b, value_handle=0x002c, uuid=00000001-1000-1000-8000-00805f9b34fb, prop=0x10
111 		 Descriptor: handle=0x002d, uuid=00002902-0000-1000-8000-00805f9b34fb
112 	 Characteristic: declaration_handle=0x002e, value_handle=0x002f, uuid=00000002-1000-1000-8000-00805f9b34fb, prop=0x08
113 	 Characteristic: declaration_handle=0x0030, value_handle=0x0031, uuid=00000003-1000-1000-8000-00805f9b34fb, prop=0x02
114 */
115 // clang-format on
116 
117 /* This test verifies that DatabaseBuilder will properly discover database
118  * content from a remote device. It also verify that after the discovery is
119  * done, returned database is equal to the discovered one */
TEST(DatabaseBuilderSampleDeviceTest,DoDiscovery)120 TEST(DatabaseBuilderSampleDeviceTest, DoDiscovery) {
121   DatabaseBuilder builder;
122 
123   EXPECT_FALSE(builder.InProgress());
124 
125   // At start of discovery, builder will receive All services in order from
126   // lower layers.
127   builder.AddService(0x0001, 0x0007, SERVICE_1_UUID, true);
128 
129   // The moment we receive first service, we are in progress
130   // TODO: we should be able to set InProgress state once we sent GATT request,
131   // not when it's back and parsed
132   EXPECT_TRUE(builder.InProgress());
133 
134   builder.AddService(0x0008, 0x0008, SERVICE_2_UUID, true);
135   builder.AddService(0x0009, 0x000c, SERVICE_3_UUID, true);
136   builder.AddService(0x000d, 0x001a, SERVICE_4_UUID, true);
137   builder.AddService(0x001b, 0x0029, SERVICE_5_UUID, true);
138   builder.AddService(0x002a, 0x0031, SERVICE_6_UUID, true);
139 
140   // At this moment, all services are received, stack will grab them one and one
141   // to discover their content.
142   EXPECT_TRUE(builder.StartNextServiceExploration());
143 
144   // Grabbing first service, to start Included Service and Characteristic
145   // discovery
146   EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0001, 0x0007));
147 
148   builder.AddCharacteristic(0x0002, 0x0003, SERVICE_1_CHAR_1_UUID, 0x02);
149   builder.AddCharacteristic(0x0004, 0x0005, SERVICE_1_CHAR_2_UUID, 0x02);
150   builder.AddCharacteristic(0x0006, 0x0007, SERVICE_1_CHAR_3_UUID, 0x02);
151 
152   // All characteristics were discovered, stack will try to look for
153   // descriptors. Since there is no space for descriptors, builder should return
154   // nothing more to discover
155   EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
156 
157   // Service with handles 0x0008, 0x0008 is skipped for exploration - we know
158   // it's empty.
159   EXPECT_TRUE(builder.StartNextServiceExploration());
160   EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0009, 0x000c));
161 
162   builder.AddCharacteristic(0x000a, 0x000b, SERVICE_3_CHAR_1_UUID, 0x12);
163 
164   EXPECT_EQ(builder.NextDescriptorRangeToExplore(),
165             make_pair_u16(0x000c, 0x000c));
166 
167   builder.AddDescriptor(0x000c, SERVICE_3_CHAR_1_DESC_1_UUID);
168 
169   // All descriptors were explored
170   EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
171 
172   EXPECT_TRUE(builder.StartNextServiceExploration());
173   EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x000d, 0x001a));
174 
175   builder.AddCharacteristic(0x000e, 0x000f, SERVICE_4_CHAR_1_UUID, 0x0a);
176   builder.AddCharacteristic(0x0010, 0x0011, SERVICE_4_CHAR_2_UUID, 0x0a);
177   builder.AddCharacteristic(0x0012, 0x0013, SERVICE_4_CHAR_3_UUID, 0x02);
178   builder.AddCharacteristic(0x0014, 0x0015, SERVICE_4_CHAR_4_UUID, 0x0a);
179   builder.AddCharacteristic(0x0016, 0x0017, SERVICE_4_CHAR_5_UUID, 0x0e);
180   builder.AddCharacteristic(0x0018, 0x0019, SERVICE_4_CHAR_6_UUID, 0x12);
181 
182   // Just last Characteristic have space for descriptor
183   EXPECT_EQ(builder.NextDescriptorRangeToExplore(),
184             make_pair_u16(0x001a, 0x001a));
185 
186   builder.AddDescriptor(0x001a, SERVICE_4_CHAR_6_DESC_1_UUID);
187 
188   // All descriptors were explored
189   EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
190 
191   EXPECT_TRUE(builder.StartNextServiceExploration());
192   EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x001b, 0x0029));
193 
194   builder.AddCharacteristic(0x001c, 0x001d, SERVICE_5_CHAR_1_UUID, 0x02);
195   builder.AddCharacteristic(0x001e, 0x001f, SERVICE_5_CHAR_2_UUID, 0x02);
196   builder.AddCharacteristic(0x0020, 0x0021, SERVICE_5_CHAR_3_UUID, 0x02);
197   builder.AddCharacteristic(0x0022, 0x0023, SERVICE_5_CHAR_4_UUID, 0x02);
198   builder.AddCharacteristic(0x0024, 0x0025, SERVICE_5_CHAR_5_UUID, 0x02);
199   builder.AddCharacteristic(0x0026, 0x0027, SERVICE_5_CHAR_6_UUID, 0x02);
200   builder.AddCharacteristic(0x0028, 0x0029, SERVICE_5_CHAR_7_UUID, 0x02);
201 
202   // No space for descriptors
203   EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
204 
205   EXPECT_TRUE(builder.StartNextServiceExploration());
206   EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x002a, 0x0031));
207 
208   builder.AddCharacteristic(0x002b, 0x002c, SERVICE_6_CHAR_1_UUID, 0x10);
209   builder.AddCharacteristic(0x002e, 0x002f, SERVICE_6_CHAR_2_UUID, 0x08);
210   builder.AddCharacteristic(0x0030, 0x0031, SERVICE_6_CHAR_3_UUID, 0x02);
211 
212   // Just one Characteristic have space for descriptor
213   EXPECT_EQ(builder.NextDescriptorRangeToExplore(),
214             make_pair_u16(0x002d, 0x002d));
215 
216   builder.AddDescriptor(0x002d, SERVICE_6_CHAR_1_DESC_1_UUID);
217 
218   // All descriptors were explored
219   EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
220 
221   EXPECT_FALSE(builder.StartNextServiceExploration());
222 
223   EXPECT_TRUE(builder.InProgress());
224   Database result = builder.Build();
225   EXPECT_FALSE(builder.InProgress());
226 
227   // verify that the returned database matches what was discovered
228   auto service = result.Services().begin();
229   EXPECT_EQ(service->handle, 0x0001);
230   EXPECT_EQ(service->uuid, SERVICE_1_UUID);
231 
232   EXPECT_EQ(service->characteristics[0].uuid, SERVICE_1_CHAR_1_UUID);
233   EXPECT_EQ(service->characteristics[1].uuid, SERVICE_1_CHAR_2_UUID);
234   EXPECT_EQ(service->characteristics[2].uuid, SERVICE_1_CHAR_3_UUID);
235 
236   service++;
237   EXPECT_EQ(service->uuid, SERVICE_2_UUID);
238 
239   service++;
240   EXPECT_EQ(service->uuid, SERVICE_3_UUID);
241   EXPECT_EQ(service->characteristics[0].uuid, SERVICE_3_CHAR_1_UUID);
242   EXPECT_EQ(service->characteristics[0].descriptors[0].uuid,
243             SERVICE_3_CHAR_1_DESC_1_UUID);
244 
245   service++;
246   EXPECT_EQ(service->uuid, SERVICE_4_UUID);
247   EXPECT_EQ(service->characteristics[0].uuid, SERVICE_4_CHAR_1_UUID);
248   EXPECT_EQ(service->characteristics[1].uuid, SERVICE_4_CHAR_2_UUID);
249   EXPECT_EQ(service->characteristics[2].uuid, SERVICE_4_CHAR_3_UUID);
250   EXPECT_EQ(service->characteristics[3].uuid, SERVICE_4_CHAR_4_UUID);
251   EXPECT_EQ(service->characteristics[4].uuid, SERVICE_4_CHAR_5_UUID);
252   EXPECT_EQ(service->characteristics[5].uuid, SERVICE_4_CHAR_6_UUID);
253   EXPECT_EQ(service->characteristics[5].descriptors[0].uuid,
254             SERVICE_4_CHAR_6_DESC_1_UUID);
255 
256   service++;
257   EXPECT_EQ(service->uuid, SERVICE_5_UUID);
258   EXPECT_EQ(service->characteristics[0].uuid, SERVICE_5_CHAR_1_UUID);
259   EXPECT_EQ(service->characteristics[1].uuid, SERVICE_5_CHAR_2_UUID);
260   EXPECT_EQ(service->characteristics[2].uuid, SERVICE_5_CHAR_3_UUID);
261   EXPECT_EQ(service->characteristics[3].uuid, SERVICE_5_CHAR_4_UUID);
262   EXPECT_EQ(service->characteristics[4].uuid, SERVICE_5_CHAR_5_UUID);
263   EXPECT_EQ(service->characteristics[5].uuid, SERVICE_5_CHAR_6_UUID);
264   EXPECT_EQ(service->characteristics[6].uuid, SERVICE_5_CHAR_7_UUID);
265 
266   service++;
267   EXPECT_EQ(service->uuid, SERVICE_6_UUID);
268   EXPECT_EQ(service->characteristics[0].uuid, SERVICE_6_CHAR_1_UUID);
269   EXPECT_EQ(service->characteristics[0].descriptors[0].uuid,
270             SERVICE_6_CHAR_1_DESC_1_UUID);
271   EXPECT_EQ(service->characteristics[1].uuid, SERVICE_6_CHAR_2_UUID);
272   EXPECT_EQ(service->characteristics[2].uuid, SERVICE_6_CHAR_3_UUID);
273 }
274 
275 }  // namespace gatt
276