1 /*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18 #include <string.h>
19
20 #include <cstdint>
21 #include <map>
22 #include <memory>
23 #include <string>
24
25 #include "bta/gatt/bta_gattc_int.h"
26 #include "common/message_loop_thread.h"
27 #include "osi/include/allocator.h"
28 #include "stack/gatt/gatt_int.h"
29
30 // TODO put this in common place
31 extern std::map<std::string, int> mock_function_count_map;
32
33 namespace param {
34 struct {
35 uint16_t conn_id;
36 tGATT_STATUS status;
37 uint16_t handle;
38 uint16_t len;
39 uint8_t* value;
40 void* data;
41 } bta_gatt_read_complete_callback;
42 } // namespace param
bta_gatt_read_complete_callback(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)43 void bta_gatt_read_complete_callback(uint16_t conn_id, tGATT_STATUS status,
44 uint16_t handle, uint16_t len,
45 uint8_t* value, void* data) {
46 param::bta_gatt_read_complete_callback.conn_id = conn_id;
47 param::bta_gatt_read_complete_callback.status = status;
48 param::bta_gatt_read_complete_callback.handle = handle;
49 param::bta_gatt_read_complete_callback.len = len;
50 param::bta_gatt_read_complete_callback.value = value;
51 param::bta_gatt_read_complete_callback.data = data;
52 }
53
54 namespace param {
55 struct {
56 uint16_t conn_id;
57 tGATT_STATUS status;
58 uint16_t handle;
59 uint16_t len;
60 const uint8_t* value;
61 void* data;
62 } bta_gatt_write_complete_callback;
63 } // namespace param
64
bta_gatt_write_complete_callback(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void * data)65 void bta_gatt_write_complete_callback(uint16_t conn_id, tGATT_STATUS status,
66 uint16_t handle, uint16_t len,
67 const uint8_t* value, void* data) {
68 param::bta_gatt_write_complete_callback.conn_id = conn_id;
69 param::bta_gatt_write_complete_callback.status = status;
70 param::bta_gatt_write_complete_callback.handle = handle;
71 param::bta_gatt_write_complete_callback.len = len;
72 param::bta_gatt_write_complete_callback.value = value;
73 param::bta_gatt_write_complete_callback.data = data;
74 }
75
76 namespace param {
77 struct {
78 uint16_t conn_id;
79 tGATT_STATUS status;
80 void* data;
81 } bta_gatt_configure_mtu_complete_callback;
82 } // namespace param
83
bta_gatt_configure_mtu_complete_callback(uint16_t conn_id,tGATT_STATUS status,void * data)84 void bta_gatt_configure_mtu_complete_callback(uint16_t conn_id,
85 tGATT_STATUS status, void* data) {
86 param::bta_gatt_configure_mtu_complete_callback.conn_id = conn_id;
87 param::bta_gatt_configure_mtu_complete_callback.status = status;
88 param::bta_gatt_configure_mtu_complete_callback.data = data;
89 }
90
91 namespace param {
92 struct {
93 tBTA_GATTC_EVT event;
94 tBTA_GATTC* p_data;
95 } bta_gattc_event_complete_callback;
96 } // namespace param
97
bta_gattc_event_complete_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)98 void bta_gattc_event_complete_callback(tBTA_GATTC_EVT event,
99 tBTA_GATTC* p_data) {
100 param::bta_gattc_event_complete_callback.event = event;
101 param::bta_gattc_event_complete_callback.p_data = p_data;
102 }
103
104 class BtaGattTest : public ::testing::Test {
105 protected:
SetUp()106 void SetUp() override {
107 mock_function_count_map.clear();
108 param::bta_gatt_read_complete_callback = {};
109 param::bta_gatt_write_complete_callback = {};
110 param::bta_gatt_configure_mtu_complete_callback = {};
111 param::bta_gattc_event_complete_callback = {};
112 }
113
TearDown()114 void TearDown() override {}
115
116 tBTA_GATTC_RCB app_control_block = {
117 .p_cback = bta_gattc_event_complete_callback,
118 };
119
120 tGATT_CL_COMPLETE gatt_cl_complete = {
121 .att_value =
122 {
123 .conn_id = 1,
124 .handle = 2,
125 .offset = 3,
126 .auth_req = GATT_AUTH_REQ_NONE,
127 .value = {10, 11, 12, 13},
128 .len = 4, // length of value above
129 },
130 };
131
132 tBTA_GATTC_SERV service_control_block = {
133 .mtu = 456,
134 };
135 tBTA_GATTC_DATA command_queue;
136
137 tBTA_GATTC_CLCB client_channel_control_block = {
138 .p_q_cmd = &command_queue,
139 .p_rcb = &app_control_block,
140 .p_srcb = &service_control_block,
141 .bta_conn_id = 456,
142 };
143 };
144
TEST_F(BtaGattTest,bta_gattc_op_cmpl_read)145 TEST_F(BtaGattTest, bta_gattc_op_cmpl_read) {
146 command_queue = {
147 .api_read = // tBTA_GATTC_API_READ
148 {
149 .hdr =
150 {
151 .event = BTA_GATTC_API_READ_EVT,
152 },
153 .handle = 123,
154 .read_cb = bta_gatt_read_complete_callback,
155 .read_cb_data = static_cast<void*>(this),
156 },
157 };
158
159 client_channel_control_block.p_q_cmd = &command_queue;
160
161 tBTA_GATTC_DATA data = {
162 .op_cmpl =
163 {
164 .op_code = GATTC_OPTYPE_READ,
165 .status = GATT_OUT_OF_RANGE,
166 .p_cmpl = &gatt_cl_complete,
167 },
168 };
169
170 bta_gattc_op_cmpl(&client_channel_control_block, &data);
171 ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]);
172 ASSERT_EQ(456, param::bta_gatt_read_complete_callback.conn_id);
173 ASSERT_EQ(GATT_OUT_OF_RANGE, param::bta_gatt_read_complete_callback.status);
174 ASSERT_EQ(123, param::bta_gatt_read_complete_callback.handle);
175 ASSERT_EQ(4, param::bta_gatt_read_complete_callback.len);
176 ASSERT_EQ(10, param::bta_gatt_read_complete_callback.value[0]);
177 ASSERT_EQ(this, param::bta_gatt_read_complete_callback.data);
178 }
179
TEST_F(BtaGattTest,bta_gattc_op_cmpl_write)180 TEST_F(BtaGattTest, bta_gattc_op_cmpl_write) {
181 command_queue = {
182 .api_write = // tBTA_GATTC_API_WRITE
183 {
184 .hdr =
185 {
186 .event = BTA_GATTC_API_WRITE_EVT,
187 },
188 .handle = 123,
189 .write_cb = bta_gatt_write_complete_callback,
190 .write_cb_data = static_cast<void*>(this),
191 },
192 };
193
194 client_channel_control_block.p_q_cmd = &command_queue;
195
196 tBTA_GATTC_DATA data = {
197 .op_cmpl =
198 {
199 .op_code = GATTC_OPTYPE_WRITE,
200 .status = GATT_OUT_OF_RANGE,
201 .p_cmpl = &gatt_cl_complete,
202 },
203 };
204
205 bta_gattc_op_cmpl(&client_channel_control_block, &data);
206 ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]);
207 ASSERT_EQ(456, param::bta_gatt_write_complete_callback.conn_id);
208 ASSERT_EQ(2, param::bta_gatt_write_complete_callback.handle);
209 ASSERT_EQ(GATT_OUT_OF_RANGE, param::bta_gatt_write_complete_callback.status);
210 ASSERT_EQ(this, param::bta_gatt_write_complete_callback.data);
211 }
212
TEST_F(BtaGattTest,bta_gattc_op_cmpl_config)213 TEST_F(BtaGattTest, bta_gattc_op_cmpl_config) {
214 command_queue = {
215 .api_mtu = // tBTA_GATTC_API_CFG_MTU
216 {
217 .hdr =
218 {
219 .event = BTA_GATTC_API_CFG_MTU_EVT,
220 },
221 .mtu_cb = bta_gatt_configure_mtu_complete_callback,
222 .mtu_cb_data = static_cast<void*>(this),
223 },
224 };
225
226 client_channel_control_block.p_q_cmd = &command_queue;
227
228 tBTA_GATTC_DATA data = {
229 .op_cmpl =
230 {
231 .op_code = GATTC_OPTYPE_CONFIG,
232 .status = GATT_PRC_IN_PROGRESS,
233 },
234 };
235
236 bta_gattc_op_cmpl(&client_channel_control_block, &data);
237 ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]);
238 ASSERT_EQ(456, param::bta_gatt_configure_mtu_complete_callback.conn_id);
239
240 ASSERT_EQ(GATT_PRC_IN_PROGRESS,
241 param::bta_gatt_configure_mtu_complete_callback.status);
242 ASSERT_EQ(this, param::bta_gatt_configure_mtu_complete_callback.data);
243 }
244
TEST_F(BtaGattTest,bta_gattc_op_cmpl_execute)245 TEST_F(BtaGattTest, bta_gattc_op_cmpl_execute) {
246 command_queue = {
247 .api_exec = // tBTA_GATTC_API_EXEC
248 {
249 .hdr =
250 {
251 .event = BTA_GATTC_API_EXEC_EVT,
252 },
253 },
254 };
255
256 client_channel_control_block.p_q_cmd = &command_queue;
257
258 tBTA_GATTC_DATA data = {
259 .op_cmpl =
260 {
261 .op_code = GATTC_OPTYPE_EXE_WRITE,
262 },
263 };
264
265 bta_gattc_op_cmpl(&client_channel_control_block, &data);
266 ASSERT_EQ(BTA_GATTC_EXEC_EVT, param::bta_gattc_event_complete_callback.event);
267 ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]);
268 }
269
TEST_F(BtaGattTest,bta_gattc_op_cmpl_read_interrupted)270 TEST_F(BtaGattTest, bta_gattc_op_cmpl_read_interrupted) {
271 command_queue = {
272 .api_read = // tBTA_GATTC_API_READ
273 {
274 .hdr =
275 {
276 .event = BTA_GATTC_API_READ_EVT,
277 },
278 .handle = 123,
279 .read_cb = bta_gatt_read_complete_callback,
280 .read_cb_data = static_cast<void*>(this),
281 },
282 };
283
284 client_channel_control_block.p_q_cmd = &command_queue;
285
286 // Create interrupt condition
287 client_channel_control_block.auto_update = BTA_GATTC_DISC_WAITING;
288 client_channel_control_block.p_srcb->srvc_hdl_chg = 1;
289
290 tBTA_GATTC_DATA data = {
291 .op_cmpl =
292 {
293 .op_code = GATTC_OPTYPE_READ,
294 .status = GATT_OUT_OF_RANGE,
295 .p_cmpl = &gatt_cl_complete,
296 },
297 };
298
299 bta_gattc_op_cmpl(&client_channel_control_block, &data);
300 ASSERT_EQ(GATT_ERROR, param::bta_gatt_read_complete_callback.status);
301 }
302