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