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