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_builder.h"
20 
21 #include <gtest/gtest.h>
22 
23 #include <iterator>
24 #include <utility>
25 
26 #include "types/bluetooth/uuid.h"
27 
28 using bluetooth::Uuid;
29 
30 namespace gatt {
31 
32 namespace {
33 /* make_pair doesn't work well with ASSERT_EQ, have own helper instead */
make_pair_u16(uint16_t first,uint16_t second)34 inline std::pair<uint16_t, uint16_t> make_pair_u16(uint16_t first, uint16_t second) {
35   return std::make_pair(first, second);
36 }
37 
38 Uuid SERVICE_1_UUID = Uuid::FromString("00001800-0000-1000-8000-00805f9b34fb");
39 Uuid SERVICE_2_UUID = Uuid::FromString("00001801-0000-1000-8000-00805f9b34fb");
40 Uuid SERVICE_3_UUID = Uuid::FromString("0000180f-0000-1000-8000-00805f9b34fb");
41 Uuid SERVICE_4_UUID = Uuid::FromString("0000fef5-0000-1000-8000-00805f9b34fb");
42 Uuid SERVICE_5_UUID = Uuid::FromString("0000180a-0000-1000-8000-00805f9b34fb");
43 Uuid SERVICE_1_CHAR_1_UUID = Uuid::FromString("00002a00-0000-1000-8000-00805f9b34fb");
44 Uuid SERVICE_1_CHAR_1_DESC_1_UUID = Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb");
45 
46 }  // namespace
47 
48 /* Verify adding empty service works ok */
TEST(DatabaseBuilderTest,EmptyServiceAddTest)49 TEST(DatabaseBuilderTest, EmptyServiceAddTest) {
50   DatabaseBuilder builder;
51 
52   EXPECT_FALSE(builder.InProgress());
53 
54   // Simple database, just one empty
55   builder.AddService(0x0001, 0x0001, SERVICE_1_UUID, true);
56   EXPECT_FALSE(builder.StartNextServiceExploration());
57 
58   Database result = builder.Build();
59 
60   // verify that the returned database matches what was discovered
61   auto service = result.Services().begin();
62   ASSERT_EQ(service->handle, 0x0001);
63   ASSERT_EQ(service->end_handle, 0x0001);
64   ASSERT_EQ(service->is_primary, true);
65   ASSERT_EQ(service->uuid, SERVICE_1_UUID);
66 }
67 
68 /* Verify adding service, characteristic and descriptor work */
TEST(DatabaseBuilderTest,DescriptorAddTest)69 TEST(DatabaseBuilderTest, DescriptorAddTest) {
70   DatabaseBuilder builder;
71 
72   EXPECT_FALSE(builder.InProgress());
73 
74   // Simple database, just one empty
75   builder.AddService(0x0001, 0x000f, SERVICE_1_UUID, true);
76   builder.AddCharacteristic(0x0002, 0x0003, SERVICE_1_CHAR_1_UUID, 0x02);
77   builder.AddDescriptor(0x0004, SERVICE_1_CHAR_1_DESC_1_UUID);
78 
79   Database result = builder.Build();
80 
81   // verify that the returned database matches what was discovered
82   auto service = result.Services().begin();
83   ASSERT_EQ(service->handle, 0x0001);
84   ASSERT_EQ(service->end_handle, 0x000f);
85   ASSERT_EQ(service->is_primary, true);
86   ASSERT_EQ(service->uuid, SERVICE_1_UUID);
87 
88   ASSERT_EQ(service->characteristics[0].uuid, SERVICE_1_CHAR_1_UUID);
89   ASSERT_EQ(service->characteristics[0].declaration_handle, 0x0002);
90   ASSERT_EQ(service->characteristics[0].value_handle, 0x0003);
91   ASSERT_EQ(service->characteristics[0].properties, 0x02);
92 
93   ASSERT_EQ(service->characteristics[0].descriptors[0].uuid, SERVICE_1_CHAR_1_DESC_1_UUID);
94   ASSERT_EQ(service->characteristics[0].descriptors[0].handle, 0x0004);
95 }
96 
97 /* This test verifies that DatabaseBuilder properly handle discovery of
98  * secondary service, that is added to the discovery queue from included service
99  * definition. Such service might come out of order.  */
TEST(DatabaseBuilderTest,SecondaryServiceOutOfOrderTest)100 TEST(DatabaseBuilderTest, SecondaryServiceOutOfOrderTest) {
101   DatabaseBuilder builder;
102 
103   EXPECT_FALSE(builder.InProgress());
104 
105   // At start of discovery, builder will receive All services in order from
106   // lower layers.
107   builder.AddService(0x0001, 0x000f, SERVICE_1_UUID, true);
108   builder.AddService(0x0030, 0x003f, SERVICE_3_UUID, true);
109   builder.AddService(0x0050, 0x005f, SERVICE_5_UUID, true);
110 
111   // First service skipped, no place for handles
112   EXPECT_TRUE(builder.StartNextServiceExploration());
113   ASSERT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0001, 0x000f));
114 
115   // For this test, content of first service is irrevelant
116 
117   EXPECT_TRUE(builder.StartNextServiceExploration());
118   // Grabbing first service, to start Included Service and Characteristic
119   // discovery
120   ASSERT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0030, 0x003f));
121 
122   builder.AddIncludedService(0x0031, SERVICE_4_UUID, 0x0040, 0x004f);
123   builder.AddIncludedService(0x0032, SERVICE_2_UUID, 0x0020, 0x002f);
124 
125   /* Secondary service exploration */
126   EXPECT_TRUE(builder.StartNextServiceExploration());
127   ASSERT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0020, 0x002f));
128 
129   /* Secondary service exploration */
130   EXPECT_TRUE(builder.StartNextServiceExploration());
131   ASSERT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0040, 0x004f));
132 
133   /* Back to primary service exploration */
134   EXPECT_TRUE(builder.StartNextServiceExploration());
135   ASSERT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0050, 0x005f));
136 
137   Database result = builder.Build();
138 
139   // verify that the returned database matches what was discovered
140   auto service = result.Services().begin();
141   ASSERT_EQ(service->handle, 0x0001);
142   ASSERT_EQ(service->is_primary, true);
143   ASSERT_EQ(service->uuid, SERVICE_1_UUID);
144 
145   service++;
146   ASSERT_EQ(service->handle, 0x0020);
147   ASSERT_EQ(service->end_handle, 0x002f);
148   ASSERT_EQ(service->uuid, SERVICE_2_UUID);
149   ASSERT_EQ(service->is_primary, false);
150 
151   service++;
152   ASSERT_EQ(service->handle, 0x0030);
153   ASSERT_EQ(service->end_handle, 0x003f);
154   ASSERT_EQ(service->uuid, SERVICE_3_UUID);
155   ASSERT_EQ(service->is_primary, true);
156   ASSERT_EQ(service->included_services.size(), (size_t)2);
157   ASSERT_EQ(service->included_services[0].start_handle, 0x0040);
158   ASSERT_EQ(service->included_services[0].end_handle, 0x004f);
159   ASSERT_EQ(service->included_services[1].start_handle, 0x0020);
160   ASSERT_EQ(service->included_services[1].end_handle, 0x002f);
161 
162   service++;
163   ASSERT_EQ(service->handle, 0x0040);
164   ASSERT_EQ(service->uuid, SERVICE_4_UUID);
165   ASSERT_EQ(service->is_primary, false);
166 
167   service++;
168   ASSERT_EQ(service->handle, 0x0050);
169   ASSERT_EQ(service->uuid, SERVICE_5_UUID);
170   ASSERT_EQ(service->is_primary, true);
171 
172   service++;
173   ASSERT_EQ(service, result.Services().end());
174 }
175 
176 }  // namespace gatt
177