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 "stack/gatt/gatt_int.h"
28
29 // TODO put this in common place
30 extern std::map<std::string, int> mock_function_count_map;
31
32 namespace param {
33 struct {
34 uint16_t conn_id;
35 tGATT_STATUS status;
36 uint16_t handle;
37 uint16_t len;
38 uint8_t* value;
39 void* data;
40 } bta_gatt_read_complete_callback;
41 } // 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)42 void bta_gatt_read_complete_callback(uint16_t conn_id, tGATT_STATUS status,
43 uint16_t handle, uint16_t len,
44 uint8_t* value, void* data) {
45 param::bta_gatt_read_complete_callback.conn_id = conn_id;
46 param::bta_gatt_read_complete_callback.status = status;
47 param::bta_gatt_read_complete_callback.handle = handle;
48 param::bta_gatt_read_complete_callback.len = len;
49 param::bta_gatt_read_complete_callback.value = value;
50 param::bta_gatt_read_complete_callback.data = data;
51 }
52
53 namespace param {
54 struct {
55 uint16_t conn_id;
56 tGATT_STATUS status;
57 uint16_t handle;
58 void* data;
59 } bta_gatt_write_complete_callback;
60 } // namespace param
61
bta_gatt_write_complete_callback(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,void * data)62 void bta_gatt_write_complete_callback(uint16_t conn_id, tGATT_STATUS status,
63 uint16_t handle, void* data) {
64 param::bta_gatt_write_complete_callback.conn_id = conn_id;
65 param::bta_gatt_write_complete_callback.status = status;
66 param::bta_gatt_write_complete_callback.handle = handle;
67 param::bta_gatt_write_complete_callback.data = data;
68 }
69
70 namespace param {
71 struct {
72 uint16_t conn_id;
73 tGATT_STATUS status;
74 void* data;
75 } bta_gatt_configure_mtu_complete_callback;
76 } // namespace param
77
bta_gatt_configure_mtu_complete_callback(uint16_t conn_id,tGATT_STATUS status,void * data)78 void bta_gatt_configure_mtu_complete_callback(uint16_t conn_id,
79 tGATT_STATUS status, void* data) {
80 param::bta_gatt_configure_mtu_complete_callback.conn_id = conn_id;
81 param::bta_gatt_configure_mtu_complete_callback.status = status;
82 param::bta_gatt_configure_mtu_complete_callback.data = data;
83 }
84
85 namespace param {
86 struct {
87 tBTA_GATTC_EVT event;
88 tBTA_GATTC* p_data;
89 } bta_gattc_event_complete_callback;
90 } // namespace param
91
bta_gattc_event_complete_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)92 void bta_gattc_event_complete_callback(tBTA_GATTC_EVT event,
93 tBTA_GATTC* p_data) {
94 param::bta_gattc_event_complete_callback.event = event;
95 param::bta_gattc_event_complete_callback.p_data = p_data;
96 }
97
98 class BtaGattTest : public ::testing::Test {
99 protected:
SetUp()100 void SetUp() override {
101 mock_function_count_map.clear();
102 param::bta_gatt_read_complete_callback = {};
103 param::bta_gatt_write_complete_callback = {};
104 param::bta_gatt_configure_mtu_complete_callback = {};
105 param::bta_gattc_event_complete_callback = {};
106 }
107
TearDown()108 void TearDown() override {}
109
110 tBTA_GATTC_RCB app_control_block = {
111 .p_cback = bta_gattc_event_complete_callback,
112 };
113
114 tGATT_CL_COMPLETE gatt_cl_complete = {
115 .att_value =
116 {
117 .conn_id = 1,
118 .handle = 2,
119 .offset = 3,
120 .auth_req = GATT_AUTH_REQ_NONE,
121 .value = {10, 11, 12, 13},
122 .len = 4, // length of value above
123 },
124 };
125
126 tBTA_GATTC_SERV service_control_block = {
127 .mtu = 456,
128 };
129 tBTA_GATTC_DATA command_queue;
130
131 tBTA_GATTC_CLCB client_channel_control_block = {
132 .p_q_cmd = &command_queue,
133 .p_rcb = &app_control_block,
134 .p_srcb = &service_control_block,
135 .bta_conn_id = 456,
136 };
137 };
138
TEST_F(BtaGattTest,bta_gattc_op_cmpl_read)139 TEST_F(BtaGattTest, bta_gattc_op_cmpl_read) {
140 command_queue = {
141 .api_read = // tBTA_GATTC_API_READ
142 {
143 .hdr =
144 {
145 .event = BTA_GATTC_API_READ_EVT,
146 },
147 .handle = 123,
148 .read_cb = bta_gatt_read_complete_callback,
149 .read_cb_data = static_cast<void*>(this),
150 },
151 };
152
153 client_channel_control_block.p_q_cmd = &command_queue;
154
155 tBTA_GATTC_DATA data = {
156 .op_cmpl =
157 {
158 .op_code = GATTC_OPTYPE_READ,
159 .status = GATT_OUT_OF_RANGE,
160 .p_cmpl = &gatt_cl_complete,
161 },
162 };
163
164 bta_gattc_op_cmpl(&client_channel_control_block, &data);
165 ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]);
166 ASSERT_EQ(456, param::bta_gatt_read_complete_callback.conn_id);
167 ASSERT_EQ(GATT_OUT_OF_RANGE, param::bta_gatt_read_complete_callback.status);
168 ASSERT_EQ(123, param::bta_gatt_read_complete_callback.handle);
169 ASSERT_EQ(4, param::bta_gatt_read_complete_callback.len);
170 ASSERT_EQ(10, param::bta_gatt_read_complete_callback.value[0]);
171 ASSERT_EQ(this, param::bta_gatt_read_complete_callback.data);
172 }
173
TEST_F(BtaGattTest,bta_gattc_op_cmpl_write)174 TEST_F(BtaGattTest, bta_gattc_op_cmpl_write) {
175 command_queue = {
176 .api_write = // tBTA_GATTC_API_WRITE
177 {
178 .hdr =
179 {
180 .event = BTA_GATTC_API_WRITE_EVT,
181 },
182 .handle = 123,
183 .write_cb = bta_gatt_write_complete_callback,
184 .write_cb_data = static_cast<void*>(this),
185 },
186 };
187
188 client_channel_control_block.p_q_cmd = &command_queue;
189
190 tBTA_GATTC_DATA data = {
191 .op_cmpl =
192 {
193 .op_code = GATTC_OPTYPE_WRITE,
194 .status = GATT_OUT_OF_RANGE,
195 .p_cmpl = &gatt_cl_complete,
196 },
197 };
198
199 bta_gattc_op_cmpl(&client_channel_control_block, &data);
200 ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]);
201 ASSERT_EQ(456, param::bta_gatt_write_complete_callback.conn_id);
202 ASSERT_EQ(2, param::bta_gatt_write_complete_callback.handle);
203 ASSERT_EQ(GATT_OUT_OF_RANGE, param::bta_gatt_write_complete_callback.status);
204 ASSERT_EQ(this, param::bta_gatt_write_complete_callback.data);
205 }
206
TEST_F(BtaGattTest,bta_gattc_op_cmpl_config)207 TEST_F(BtaGattTest, bta_gattc_op_cmpl_config) {
208 command_queue = {
209 .api_mtu = // tBTA_GATTC_API_CFG_MTU
210 {
211 .hdr =
212 {
213 .event = BTA_GATTC_API_CFG_MTU_EVT,
214 },
215 .mtu_cb = bta_gatt_configure_mtu_complete_callback,
216 .mtu_cb_data = static_cast<void*>(this),
217 },
218 };
219
220 client_channel_control_block.p_q_cmd = &command_queue;
221
222 tBTA_GATTC_DATA data = {
223 .op_cmpl =
224 {
225 .op_code = GATTC_OPTYPE_CONFIG,
226 .status = GATT_PRC_IN_PROGRESS,
227 },
228 };
229
230 bta_gattc_op_cmpl(&client_channel_control_block, &data);
231 ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]);
232 ASSERT_EQ(456, param::bta_gatt_configure_mtu_complete_callback.conn_id);
233
234 ASSERT_EQ(GATT_PRC_IN_PROGRESS,
235 param::bta_gatt_configure_mtu_complete_callback.status);
236 ASSERT_EQ(this, param::bta_gatt_configure_mtu_complete_callback.data);
237 }
238
TEST_F(BtaGattTest,bta_gattc_op_cmpl_execute)239 TEST_F(BtaGattTest, bta_gattc_op_cmpl_execute) {
240 command_queue = {
241 .api_exec = // tBTA_GATTC_API_EXEC
242 {
243 .hdr =
244 {
245 .event = BTA_GATTC_API_EXEC_EVT,
246 },
247 },
248 };
249
250 client_channel_control_block.p_q_cmd = &command_queue;
251
252 tBTA_GATTC_DATA data = {
253 .op_cmpl =
254 {
255 .op_code = GATTC_OPTYPE_EXE_WRITE,
256 },
257 };
258
259 bta_gattc_op_cmpl(&client_channel_control_block, &data);
260 ASSERT_EQ(BTA_GATTC_EXEC_EVT, param::bta_gattc_event_complete_callback.event);
261 ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]);
262 }
263
TEST_F(BtaGattTest,bta_gattc_op_cmpl_read_interrupted)264 TEST_F(BtaGattTest, bta_gattc_op_cmpl_read_interrupted) {
265 command_queue = {
266 .api_read = // tBTA_GATTC_API_READ
267 {
268 .hdr =
269 {
270 .event = BTA_GATTC_API_READ_EVT,
271 },
272 .handle = 123,
273 .read_cb = bta_gatt_read_complete_callback,
274 .read_cb_data = static_cast<void*>(this),
275 },
276 };
277
278 client_channel_control_block.p_q_cmd = &command_queue;
279
280 // Create interrupt condition
281 client_channel_control_block.auto_update = BTA_GATTC_DISC_WAITING;
282 client_channel_control_block.p_srcb->srvc_hdl_chg = 1;
283
284 tBTA_GATTC_DATA data = {
285 .op_cmpl =
286 {
287 .op_code = GATTC_OPTYPE_READ,
288 .status = GATT_OUT_OF_RANGE,
289 .p_cmpl = &gatt_cl_complete,
290 },
291 };
292
293 bta_gattc_op_cmpl(&client_channel_control_block, &data);
294 ASSERT_EQ(GATT_ERROR, param::bta_gatt_read_complete_callback.status);
295 }
296