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