/* * Copyright 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include "bta/gatt/bta_gattc_int.h" #include "common/message_loop_thread.h" #include "stack/gatt/gatt_int.h" // TODO put this in common place extern std::map mock_function_count_map; namespace param { struct { uint16_t conn_id; tGATT_STATUS status; uint16_t handle; uint16_t len; uint8_t* value; void* data; } bta_gatt_read_complete_callback; } // namespace param void bta_gatt_read_complete_callback(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, uint8_t* value, void* data) { param::bta_gatt_read_complete_callback.conn_id = conn_id; param::bta_gatt_read_complete_callback.status = status; param::bta_gatt_read_complete_callback.handle = handle; param::bta_gatt_read_complete_callback.len = len; param::bta_gatt_read_complete_callback.value = value; param::bta_gatt_read_complete_callback.data = data; } namespace param { struct { uint16_t conn_id; tGATT_STATUS status; uint16_t handle; void* data; } bta_gatt_write_complete_callback; } // namespace param void bta_gatt_write_complete_callback(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, void* data) { param::bta_gatt_write_complete_callback.conn_id = conn_id; param::bta_gatt_write_complete_callback.status = status; param::bta_gatt_write_complete_callback.handle = handle; param::bta_gatt_write_complete_callback.data = data; } namespace param { struct { uint16_t conn_id; tGATT_STATUS status; void* data; } bta_gatt_configure_mtu_complete_callback; } // namespace param void bta_gatt_configure_mtu_complete_callback(uint16_t conn_id, tGATT_STATUS status, void* data) { param::bta_gatt_configure_mtu_complete_callback.conn_id = conn_id; param::bta_gatt_configure_mtu_complete_callback.status = status; param::bta_gatt_configure_mtu_complete_callback.data = data; } namespace param { struct { tBTA_GATTC_EVT event; tBTA_GATTC* p_data; } bta_gattc_event_complete_callback; } // namespace param void bta_gattc_event_complete_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { param::bta_gattc_event_complete_callback.event = event; param::bta_gattc_event_complete_callback.p_data = p_data; } class BtaGattTest : public ::testing::Test { protected: void SetUp() override { mock_function_count_map.clear(); param::bta_gatt_read_complete_callback = {}; param::bta_gatt_write_complete_callback = {}; param::bta_gatt_configure_mtu_complete_callback = {}; param::bta_gattc_event_complete_callback = {}; } void TearDown() override {} tBTA_GATTC_RCB app_control_block = { .p_cback = bta_gattc_event_complete_callback, }; tGATT_CL_COMPLETE gatt_cl_complete = { .att_value = { .conn_id = 1, .handle = 2, .offset = 3, .auth_req = GATT_AUTH_REQ_NONE, .value = {10, 11, 12, 13}, .len = 4, // length of value above }, }; tBTA_GATTC_SERV service_control_block = { .mtu = 456, }; tBTA_GATTC_DATA command_queue; tBTA_GATTC_CLCB client_channel_control_block = { .p_q_cmd = &command_queue, .p_rcb = &app_control_block, .p_srcb = &service_control_block, .bta_conn_id = 456, }; }; TEST_F(BtaGattTest, bta_gattc_op_cmpl_read) { command_queue = { .api_read = // tBTA_GATTC_API_READ { .hdr = { .event = BTA_GATTC_API_READ_EVT, }, .handle = 123, .read_cb = bta_gatt_read_complete_callback, .read_cb_data = static_cast(this), }, }; client_channel_control_block.p_q_cmd = &command_queue; tBTA_GATTC_DATA data = { .op_cmpl = { .op_code = GATTC_OPTYPE_READ, .status = GATT_OUT_OF_RANGE, .p_cmpl = &gatt_cl_complete, }, }; bta_gattc_op_cmpl(&client_channel_control_block, &data); ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]); ASSERT_EQ(456, param::bta_gatt_read_complete_callback.conn_id); ASSERT_EQ(GATT_OUT_OF_RANGE, param::bta_gatt_read_complete_callback.status); ASSERT_EQ(123, param::bta_gatt_read_complete_callback.handle); ASSERT_EQ(4, param::bta_gatt_read_complete_callback.len); ASSERT_EQ(10, param::bta_gatt_read_complete_callback.value[0]); ASSERT_EQ(this, param::bta_gatt_read_complete_callback.data); } TEST_F(BtaGattTest, bta_gattc_op_cmpl_write) { command_queue = { .api_write = // tBTA_GATTC_API_WRITE { .hdr = { .event = BTA_GATTC_API_WRITE_EVT, }, .handle = 123, .write_cb = bta_gatt_write_complete_callback, .write_cb_data = static_cast(this), }, }; client_channel_control_block.p_q_cmd = &command_queue; tBTA_GATTC_DATA data = { .op_cmpl = { .op_code = GATTC_OPTYPE_WRITE, .status = GATT_OUT_OF_RANGE, .p_cmpl = &gatt_cl_complete, }, }; bta_gattc_op_cmpl(&client_channel_control_block, &data); ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]); ASSERT_EQ(456, param::bta_gatt_write_complete_callback.conn_id); ASSERT_EQ(2, param::bta_gatt_write_complete_callback.handle); ASSERT_EQ(GATT_OUT_OF_RANGE, param::bta_gatt_write_complete_callback.status); ASSERT_EQ(this, param::bta_gatt_write_complete_callback.data); } TEST_F(BtaGattTest, bta_gattc_op_cmpl_config) { command_queue = { .api_mtu = // tBTA_GATTC_API_CFG_MTU { .hdr = { .event = BTA_GATTC_API_CFG_MTU_EVT, }, .mtu_cb = bta_gatt_configure_mtu_complete_callback, .mtu_cb_data = static_cast(this), }, }; client_channel_control_block.p_q_cmd = &command_queue; tBTA_GATTC_DATA data = { .op_cmpl = { .op_code = GATTC_OPTYPE_CONFIG, .status = GATT_PRC_IN_PROGRESS, }, }; bta_gattc_op_cmpl(&client_channel_control_block, &data); ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]); ASSERT_EQ(456, param::bta_gatt_configure_mtu_complete_callback.conn_id); ASSERT_EQ(GATT_PRC_IN_PROGRESS, param::bta_gatt_configure_mtu_complete_callback.status); ASSERT_EQ(this, param::bta_gatt_configure_mtu_complete_callback.data); } TEST_F(BtaGattTest, bta_gattc_op_cmpl_execute) { command_queue = { .api_exec = // tBTA_GATTC_API_EXEC { .hdr = { .event = BTA_GATTC_API_EXEC_EVT, }, }, }; client_channel_control_block.p_q_cmd = &command_queue; tBTA_GATTC_DATA data = { .op_cmpl = { .op_code = GATTC_OPTYPE_EXE_WRITE, }, }; bta_gattc_op_cmpl(&client_channel_control_block, &data); ASSERT_EQ(BTA_GATTC_EXEC_EVT, param::bta_gattc_event_complete_callback.event); ASSERT_EQ(1, mock_function_count_map["osi_free_and_reset"]); } TEST_F(BtaGattTest, bta_gattc_op_cmpl_read_interrupted) { command_queue = { .api_read = // tBTA_GATTC_API_READ { .hdr = { .event = BTA_GATTC_API_READ_EVT, }, .handle = 123, .read_cb = bta_gatt_read_complete_callback, .read_cb_data = static_cast(this), }, }; client_channel_control_block.p_q_cmd = &command_queue; // Create interrupt condition client_channel_control_block.auto_update = BTA_GATTC_DISC_WAITING; client_channel_control_block.p_srcb->srvc_hdl_chg = 1; tBTA_GATTC_DATA data = { .op_cmpl = { .op_code = GATTC_OPTYPE_READ, .status = GATT_OUT_OF_RANGE, .p_cmpl = &gatt_cl_complete, }, }; bta_gattc_op_cmpl(&client_channel_control_block, &data); ASSERT_EQ(GATT_ERROR, param::bta_gatt_read_complete_callback.status); }