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