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