1 /*
2 * Copyright 2020 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 <base/logging.h>
18 #include <gtest/gtest.h>
19 #include <stdio.h>
20 #include <cstdint>
21
22 #include "osi/test/AllocationTestHarness.h"
23 #include "stack/gatt/gatt_int.h"
24 #undef LOG_TAG
25 #include "stack/gatt/gatt_sr.cc"
26 #include "types/raw_address.h"
27
28 #define MAX_UINT16 ((uint16_t)0xffff)
29
30 tGATT_CB gatt_cb;
31
32 namespace {
33
34 struct TestMutables {
35 struct {
36 uint8_t op_code_;
37 } attp_build_sr_msg;
38 struct {
39 uint16_t conn_id_{0};
40 uint32_t trans_id_{0};
41 tGATTS_REQ_TYPE type_{0xff};
42 tGATTS_DATA data_;
43 } application_request_callback;
44 struct {
45 int access_count_{0};
46 tGATT_STATUS return_status_{GATT_SUCCESS};
47 } gatts_write_attr_perm_check;
48 };
49
50 TestMutables test_state_;
51 } // namespace
52
53 namespace connection_manager {
background_connect_remove(uint8_t app_id,const RawAddress & address)54 bool background_connect_remove(uint8_t app_id, const RawAddress& address) {
55 return false;
56 }
direct_connect_remove(uint8_t app_id,const RawAddress & address)57 bool direct_connect_remove(uint8_t app_id, const RawAddress& address) {
58 return false;
59 }
60 } // namespace connection_manager
61
attp_build_sr_msg(tGATT_TCB & tcb,uint8_t op_code,tGATT_SR_MSG * p_msg)62 BT_HDR* attp_build_sr_msg(tGATT_TCB& tcb, uint8_t op_code,
63 tGATT_SR_MSG* p_msg) {
64 test_state_.attp_build_sr_msg.op_code_ = op_code;
65 return nullptr;
66 }
attp_send_cl_msg(tGATT_TCB & tcb,tGATT_CLCB * p_clcb,uint8_t op_code,tGATT_CL_MSG * p_msg)67 tGATT_STATUS attp_send_cl_msg(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
68 uint8_t op_code, tGATT_CL_MSG* p_msg) {
69 return 0;
70 }
attp_send_sr_msg(tGATT_TCB & tcb,BT_HDR * p_msg)71 tGATT_STATUS attp_send_sr_msg(tGATT_TCB& tcb, BT_HDR* p_msg) { return 0; }
btm_ble_read_sec_key_size(const RawAddress & bd_addr)72 uint8_t btm_ble_read_sec_key_size(const RawAddress& bd_addr) { return 0; }
BTM_GetSecurityFlagsByTransport(const RawAddress & bd_addr,uint8_t * p_sec_flags,tBT_TRANSPORT transport)73 bool BTM_GetSecurityFlagsByTransport(const RawAddress& bd_addr,
74 uint8_t* p_sec_flags,
75 tBT_TRANSPORT transport) {
76 return false;
77 }
gatt_act_discovery(tGATT_CLCB * p_clcb)78 void gatt_act_discovery(tGATT_CLCB* p_clcb) {}
gatt_disconnect(tGATT_TCB * p_tcb)79 bool gatt_disconnect(tGATT_TCB* p_tcb) { return false; }
gatt_get_ch_state(tGATT_TCB * p_tcb)80 tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB* p_tcb) { return 0; }
gatts_db_read_attr_value_by_type(tGATT_TCB & tcb,tGATT_SVC_DB * p_db,uint8_t op_code,BT_HDR * p_rsp,uint16_t s_handle,uint16_t e_handle,const Uuid & type,uint16_t * p_len,tGATT_SEC_FLAG sec_flag,uint8_t key_size,uint32_t trans_id,uint16_t * p_cur_handle)81 tGATT_STATUS gatts_db_read_attr_value_by_type(
82 tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp,
83 uint16_t s_handle, uint16_t e_handle, const Uuid& type, uint16_t* p_len,
84 tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id,
85 uint16_t* p_cur_handle) {
86 return 0;
87 }
gatt_set_ch_state(tGATT_TCB * p_tcb,tGATT_CH_STATE ch_state)88 void gatt_set_ch_state(tGATT_TCB* p_tcb, tGATT_CH_STATE ch_state) {}
gatts_get_service_uuid(tGATT_SVC_DB * p_db)89 Uuid* gatts_get_service_uuid(tGATT_SVC_DB* p_db) { return nullptr; }
GATTS_HandleValueIndication(uint16_t conn_id,uint16_t attr_handle,uint16_t val_len,uint8_t * p_val)90 tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle,
91 uint16_t val_len, uint8_t* p_val) {
92 return GATT_SUCCESS;
93 }
gatts_read_attr_perm_check(tGATT_SVC_DB * p_db,bool is_long,uint16_t handle,tGATT_SEC_FLAG sec_flag,uint8_t key_size)94 tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long,
95 uint16_t handle,
96 tGATT_SEC_FLAG sec_flag,
97 uint8_t key_size) {
98 return GATT_SUCCESS;
99 }
gatts_read_attr_value_by_handle(tGATT_TCB & tcb,tGATT_SVC_DB * p_db,uint8_t op_code,uint16_t handle,uint16_t offset,uint8_t * p_value,uint16_t * p_len,uint16_t mtu,tGATT_SEC_FLAG sec_flag,uint8_t key_size,uint32_t trans_id)100 tGATT_STATUS gatts_read_attr_value_by_handle(
101 tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle,
102 uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu,
103 tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id) {
104 return GATT_SUCCESS;
105 }
gatts_write_attr_perm_check(tGATT_SVC_DB * p_db,uint8_t op_code,uint16_t handle,uint16_t offset,uint8_t * p_data,uint16_t len,tGATT_SEC_FLAG sec_flag,uint8_t key_size)106 tGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* p_db, uint8_t op_code,
107 uint16_t handle, uint16_t offset,
108 uint8_t* p_data, uint16_t len,
109 tGATT_SEC_FLAG sec_flag,
110 uint8_t key_size) {
111 test_state_.gatts_write_attr_perm_check.access_count_++;
112 return test_state_.gatts_write_attr_perm_check.return_status_;
113 }
gatt_update_app_use_link_flag(tGATT_IF gatt_if,tGATT_TCB * p_tcb,bool is_add,bool check_acl_link)114 void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB* p_tcb,
115 bool is_add, bool check_acl_link) {}
get_main_message_loop()116 base::MessageLoop* get_main_message_loop() { return nullptr; }
l2cble_set_fixed_channel_tx_data_length(const RawAddress & remote_bda,uint16_t fix_cid,uint16_t tx_mtu)117 void l2cble_set_fixed_channel_tx_data_length(const RawAddress& remote_bda,
118 uint16_t fix_cid,
119 uint16_t tx_mtu) {}
SDP_AddAttribute(uint32_t handle,uint16_t attr_id,uint8_t attr_type,uint32_t attr_len,uint8_t * p_val)120 bool SDP_AddAttribute(uint32_t handle, uint16_t attr_id, uint8_t attr_type,
121 uint32_t attr_len, uint8_t* p_val) {
122 return false;
123 }
SDP_AddProtocolList(uint32_t handle,uint16_t num_elem,tSDP_PROTOCOL_ELEM * p_elem_list)124 bool SDP_AddProtocolList(uint32_t handle, uint16_t num_elem,
125 tSDP_PROTOCOL_ELEM* p_elem_list) {
126 return false;
127 }
SDP_AddServiceClassIdList(uint32_t handle,uint16_t num_services,uint16_t * p_service_uuids)128 bool SDP_AddServiceClassIdList(uint32_t handle, uint16_t num_services,
129 uint16_t* p_service_uuids) {
130 return false;
131 }
SDP_AddUuidSequence(uint32_t handle,uint16_t attr_id,uint16_t num_uuids,uint16_t * p_uuids)132 bool SDP_AddUuidSequence(uint32_t handle, uint16_t attr_id, uint16_t num_uuids,
133 uint16_t* p_uuids) {
134 return false;
135 }
SDP_CreateRecord(void)136 uint32_t SDP_CreateRecord(void) { return 0; }
137
ApplicationRequestCallback(uint16_t conn_id,uint32_t trans_id,tGATTS_REQ_TYPE type,tGATTS_DATA * p_data)138 void ApplicationRequestCallback(uint16_t conn_id, uint32_t trans_id,
139 tGATTS_REQ_TYPE type, tGATTS_DATA* p_data) {
140 test_state_.application_request_callback.conn_id_ = conn_id;
141 test_state_.application_request_callback.trans_id_ = trans_id;
142 test_state_.application_request_callback.type_ = type;
143 test_state_.application_request_callback.data_ = *p_data;
144 }
145
146 /**
147 * Test class to test selected functionality in stack/gatt/gatt_sr.cc
148 */
149 extern void allocation_tracker_uninit(void);
150 namespace {
151 uint16_t kHandle = 1;
152 bt_gatt_db_attribute_type_t kGattCharacteristicType = BTGATT_DB_CHARACTERISTIC;
153 } // namespace
154 class GattSrTest : public AllocationTestHarness {
155 protected:
SetUp()156 void SetUp() override {
157 AllocationTestHarness::SetUp();
158 // Disable our allocation tracker to allow ASAN full range
159 allocation_tracker_uninit();
160 memset(&tcb_, 0, sizeof(tcb_));
161 memset(&el_, 0, sizeof(el_));
162
163 tcb_.trans_id = 0x12345677;
164 el_.gatt_if = 1;
165 gatt_cb.cl_rcb[el_.gatt_if - 1].in_use = true;
166 gatt_cb.cl_rcb[el_.gatt_if - 1].app_cb.p_req_cb =
167 ApplicationRequestCallback;
168
169 test_state_ = TestMutables();
170 }
171
TearDown()172 void TearDown() override { AllocationTestHarness::TearDown(); }
173
174 tGATT_TCB tcb_;
175 tGATT_SRV_LIST_ELEM el_;
176 };
177
TEST_F(GattSrTest,gatts_process_write_req_request_prepare_write_no_data)178 TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_no_data) {
179 gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, 0,
180 nullptr, kGattCharacteristicType);
181 }
182
TEST_F(GattSrTest,gatts_process_write_req_request_prepare_write_max_len_no_data)183 TEST_F(GattSrTest,
184 gatts_process_write_req_request_prepare_write_max_len_no_data) {
185 gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE,
186 MAX_UINT16, nullptr, kGattCharacteristicType);
187 }
188
TEST_F(GattSrTest,gatts_process_write_req_request_prepare_write_zero_len_max_data)189 TEST_F(GattSrTest,
190 gatts_process_write_req_request_prepare_write_zero_len_max_data) {
191 uint8_t max_mem[MAX_UINT16];
192 gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, 0,
193 max_mem, kGattCharacteristicType);
194 }
195
TEST_F(GattSrTest,gatts_process_write_req_request_prepare_write_typical)196 TEST_F(GattSrTest, gatts_process_write_req_request_prepare_write_typical) {
197 uint8_t p_data[2] = {0x34, 0x12};
198 uint16_t length = static_cast<uint16_t>(sizeof(p_data) / sizeof(p_data[0]));
199 gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_PREPARE_WRITE, length,
200 p_data, kGattCharacteristicType);
201
202 CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1);
203 CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if);
204 CHECK(test_state_.application_request_callback.trans_id_ == 0x12345678);
205 CHECK(test_state_.application_request_callback.type_ ==
206 GATTS_REQ_TYPE_WRITE_CHARACTERISTIC);
207 CHECK(test_state_.application_request_callback.data_.write_req.offset ==
208 0x1234);
209 CHECK(test_state_.application_request_callback.data_.write_req.is_prep ==
210 true);
211 CHECK(test_state_.application_request_callback.data_.write_req.len == 0);
212 }
213
TEST_F(GattSrTest,gatts_process_write_req_signed_command_write_no_data)214 TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_no_data) {
215 gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, 0, nullptr,
216 kGattCharacteristicType);
217 }
218
TEST_F(GattSrTest,gatts_process_write_req_signed_command_write_max_len_no_data)219 TEST_F(GattSrTest,
220 gatts_process_write_req_signed_command_write_max_len_no_data) {
221 gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, MAX_UINT16,
222 nullptr, kGattCharacteristicType);
223 }
224
TEST_F(GattSrTest,gatts_process_write_req_signed_command_write_zero_len_max_data)225 TEST_F(GattSrTest,
226 gatts_process_write_req_signed_command_write_zero_len_max_data) {
227 uint8_t max_mem[MAX_UINT16];
228 gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, 0, max_mem,
229 kGattCharacteristicType);
230 }
231
TEST_F(GattSrTest,gatts_process_write_req_signed_command_write_typical)232 TEST_F(GattSrTest, gatts_process_write_req_signed_command_write_typical) {
233 static constexpr size_t kDataLength = 4;
234 uint8_t p_data[GATT_AUTH_SIGN_LEN + kDataLength] = {
235 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
236 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01};
237 uint16_t length = static_cast<uint16_t>(sizeof(p_data) / sizeof(p_data[0]));
238 gatts_process_write_req(tcb_, el_, kHandle, GATT_SIGN_CMD_WRITE, length,
239 p_data, kGattCharacteristicType);
240
241 CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1);
242 CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if);
243 CHECK(test_state_.application_request_callback.trans_id_ == 0x12345678);
244 CHECK(test_state_.application_request_callback.type_ ==
245 GATTS_REQ_TYPE_WRITE_CHARACTERISTIC);
246 CHECK(test_state_.application_request_callback.data_.write_req.offset == 0x0);
247 CHECK(test_state_.application_request_callback.data_.write_req.is_prep ==
248 false);
249 CHECK(test_state_.application_request_callback.data_.write_req.len ==
250 kDataLength);
251 }
252
TEST_F(GattSrTest,gatts_process_write_req_command_write_no_data)253 TEST_F(GattSrTest, gatts_process_write_req_command_write_no_data) {
254 gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, 0, nullptr,
255 kGattCharacteristicType);
256 }
257
TEST_F(GattSrTest,gatts_process_write_req_command_write_max_len_no_data)258 TEST_F(GattSrTest, gatts_process_write_req_command_write_max_len_no_data) {
259 gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, MAX_UINT16,
260 nullptr, kGattCharacteristicType);
261 }
262
TEST_F(GattSrTest,gatts_process_write_req_command_write_zero_len_max_data)263 TEST_F(GattSrTest, gatts_process_write_req_command_write_zero_len_max_data) {
264 uint8_t max_mem[MAX_UINT16];
265 gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, 0, max_mem,
266 kGattCharacteristicType);
267 }
268
TEST_F(GattSrTest,gatts_process_write_req_command_write_typical)269 TEST_F(GattSrTest, gatts_process_write_req_command_write_typical) {
270 uint8_t p_data[16] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
271 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01};
272 uint16_t length = static_cast<uint16_t>(sizeof(p_data) / sizeof(p_data[0]));
273 gatts_process_write_req(tcb_, el_, kHandle, GATT_CMD_WRITE, length, p_data,
274 kGattCharacteristicType);
275
276 CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1);
277 CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if);
278 CHECK(test_state_.application_request_callback.trans_id_ == 0x12345678);
279 CHECK(test_state_.application_request_callback.type_ ==
280 GATTS_REQ_TYPE_WRITE_CHARACTERISTIC);
281 CHECK(test_state_.application_request_callback.data_.write_req.offset == 0x0);
282 CHECK(test_state_.application_request_callback.data_.write_req.is_prep ==
283 false);
284 CHECK(test_state_.application_request_callback.data_.write_req.len == length);
285 }
286
TEST_F(GattSrTest,gatts_process_write_req_request_write_no_data)287 TEST_F(GattSrTest, gatts_process_write_req_request_write_no_data) {
288 gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, 0, nullptr,
289 kGattCharacteristicType);
290 }
291
TEST_F(GattSrTest,gatts_process_write_req_request_write_max_len_no_data)292 TEST_F(GattSrTest, gatts_process_write_req_request_write_max_len_no_data) {
293 gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, MAX_UINT16,
294 nullptr, kGattCharacteristicType);
295 }
296
TEST_F(GattSrTest,gatts_process_write_req_request_write_zero_len_max_data)297 TEST_F(GattSrTest, gatts_process_write_req_request_write_zero_len_max_data) {
298 uint8_t max_mem[MAX_UINT16];
299 gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, 0, max_mem,
300 kGattCharacteristicType);
301 }
302
TEST_F(GattSrTest,gatts_process_write_req_request_write_typical)303 TEST_F(GattSrTest, gatts_process_write_req_request_write_typical) {
304 uint8_t p_data[16] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
305 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01};
306 uint16_t length = static_cast<uint16_t>(sizeof(p_data) / sizeof(p_data[0]));
307
308 gatts_process_write_req(tcb_, el_, kHandle, GATT_REQ_WRITE, length, p_data,
309 kGattCharacteristicType);
310
311 CHECK(test_state_.gatts_write_attr_perm_check.access_count_ == 1);
312 CHECK(test_state_.application_request_callback.conn_id_ == el_.gatt_if);
313 CHECK(test_state_.application_request_callback.trans_id_ == 0x12345678);
314 CHECK(test_state_.application_request_callback.type_ ==
315 GATTS_REQ_TYPE_WRITE_CHARACTERISTIC);
316 CHECK(test_state_.application_request_callback.data_.write_req.offset == 0x0);
317 CHECK(test_state_.application_request_callback.data_.write_req.is_prep ==
318 false);
319 CHECK(test_state_.application_request_callback.data_.write_req.len == length);
320 }
321