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