1 2 // ***************************************************************************** 3 // 4 // test battery service 5 // 6 // ***************************************************************************** 7 8 9 #include <stdint.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include "CppUTest/TestHarness.h" 15 #include "CppUTest/CommandLineTestRunner.h" 16 #include "CppUTestExt/MockSupport.h" 17 18 #include "hci.h" 19 #include "gap.h" 20 #include "btstack_util.h" 21 #include "bluetooth.h" 22 #include "bluetooth_gatt.h" 23 #include "ble/le_device_db.h" 24 #include "ble/gatt-service/bond_management_service_server.h" 25 #include "bond_management_service_server_test.h" 26 #include "mock_att_server.h" 27 28 static uint32_t bond_management_features = 0xFFFFFF; 29 static uint8_t request[550]; 30 31 // mocks 32 void gap_delete_bonding(bd_addr_type_t address_type, bd_addr_t address){ 33 // traack call if needed 34 } 35 void gap_drop_link_key_for_bd_addr(bd_addr_t addr){ 36 // traack call if needed 37 } 38 int gap_link_key_iterator_init(btstack_link_key_iterator_t * it){ 39 return 1; 40 } 41 int gap_link_key_iterator_get_next(btstack_link_key_iterator_t * it, bd_addr_t bd_addr, link_key_t link_key, link_key_type_t * type){ 42 // link keys!! 43 return 0; 44 } 45 void gap_link_key_iterator_done(btstack_link_key_iterator_t * it){ 46 } 47 static hci_connection_t test_connection; 48 hci_connection_t * hci_connection_for_handle(hci_con_handle_t con_handle){ 49 memset(test_connection.address, 0x33, 6); 50 test_connection.address_type = BD_ADDR_TYPE_ACL; 51 return &test_connection; 52 } 53 int le_device_db_max_count(void){ 54 return 0; 55 } 56 void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk){ 57 } 58 // 59 60 TEST_GROUP(BOND_MANAGEMENT_SERVICE_SERVER){ 61 att_service_handler_t * service; 62 uint16_t con_handle; 63 uint16_t bm_features_value_handle; 64 uint16_t bm_control_point_value_handle; 65 66 void setup(void){ 67 // setup database 68 att_set_db(profile_data); 69 bm_features_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BOND_MANAGEMENT_FEATURE); 70 bm_control_point_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BOND_MANAGEMENT_CONTROL_POINT); 71 // setup tx power service 72 con_handle = 0x00; 73 } 74 75 void validate_write_control_point(uint32_t local_flag, const char * local_auth_str, uint8_t remote_cmd, const char * remote_auth_str, uint16_t expected_outcome){ 76 bond_management_service_server_init(local_flag); 77 service = mock_att_server_get_service(); 78 bond_management_service_server_set_authorisation_string(local_auth_str); 79 80 request[0] = remote_cmd; 81 uint16_t remote_auth_str_len = 0; 82 if (remote_auth_str != NULL) { 83 remote_auth_str_len = strlen(remote_auth_str); 84 } 85 memcpy(&request[1], remote_auth_str, remote_auth_str_len); 86 uint16_t request_len = 1 + remote_auth_str_len; 87 int response = mock_att_service_write_callback(con_handle, bm_control_point_value_handle, ATT_TRANSACTION_MODE_NONE, 0, request, request_len); 88 CHECK_EQUAL(expected_outcome, response); 89 } 90 91 void teardown(){ 92 mock_deinit(); 93 } 94 }; 95 96 TEST(BOND_MANAGEMENT_SERVICE_SERVER, lookup_attribute_handles){ 97 bond_management_service_server_init(bond_management_features); 98 service = mock_att_server_get_service(); 99 100 CHECK(bm_features_value_handle != 0); 101 CHECK(bm_control_point_value_handle != 0); 102 } 103 104 TEST(BOND_MANAGEMENT_SERVICE_SERVER, read_bm_features_value0){ 105 uint8_t response[10]; 106 uint16_t response_len; 107 108 bond_management_service_server_init(0x00); 109 service = mock_att_server_get_service(); 110 111 // invalid attribute handle 112 response_len = mock_att_service_read_callback(con_handle, 0xffff, 0xffff, response, sizeof(response)); 113 CHECK_EQUAL(0, response_len); 114 115 response_len = mock_att_service_read_callback(con_handle, bm_features_value_handle, 0, response, sizeof(response)); 116 CHECK_EQUAL(3, response_len); 117 } 118 119 120 TEST(BOND_MANAGEMENT_SERVICE_SERVER, read_bm_features_value1){ 121 uint8_t response[10]; 122 uint16_t response_len; 123 124 bond_management_service_server_init(0xFF); 125 service = mock_att_server_get_service(); 126 127 response_len = mock_att_service_read_callback(con_handle, bm_features_value_handle, 0, response, sizeof(response)); 128 CHECK_EQUAL(3, response_len); 129 } 130 131 TEST(BOND_MANAGEMENT_SERVICE_SERVER, read_bm_features_value2){ 132 uint8_t response[10]; 133 uint16_t response_len; 134 135 bond_management_service_server_init(0xFFFF); 136 service = mock_att_server_get_service(); 137 138 response_len = mock_att_service_read_callback(con_handle, bm_features_value_handle, 0, response, sizeof(response)); 139 CHECK_EQUAL(3, response_len); 140 } 141 142 TEST(BOND_MANAGEMENT_SERVICE_SERVER, read_bm_features_value3){ 143 uint8_t response[10]; 144 uint16_t response_len; 145 146 // invalid attribute handle 147 bond_management_service_server_init(0xFFFFFF); 148 service = mock_att_server_get_service(); 149 150 response_len = mock_att_service_read_callback(con_handle, bm_features_value_handle, 0, response, sizeof(response)); 151 CHECK_EQUAL(3, response_len); 152 } 153 154 155 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_bm_control_point_0){ 156 uint8_t request[520]; 157 uint16_t request_len = sizeof(request); 158 int response; 159 160 // invalid attribute handle 161 bond_management_service_server_init(0xFFFFFF); 162 service = mock_att_server_get_service(); 163 164 // wrong handle 165 response = mock_att_service_write_callback(con_handle, 0xffff, ATT_TRANSACTION_MODE_NONE, 0, request, request_len); 166 CHECK_EQUAL(response, 0); 167 168 // buffer size 0 169 response = mock_att_service_write_callback(con_handle, bm_control_point_value_handle, ATT_TRANSACTION_MODE_NONE, 0, NULL, 0); 170 CHECK_EQUAL(response, BOND_MANAGEMENT_CONTROL_POINT_OPCODE_NOT_SUPPORTED); 171 172 // wrong cmd 173 request[0] = 20; 174 response = mock_att_service_write_callback(con_handle, bm_control_point_value_handle, ATT_TRANSACTION_MODE_NONE, 0, request, request_len); 175 CHECK_EQUAL(response, BOND_MANAGEMENT_CONTROL_POINT_OPCODE_NOT_SUPPORTED); 176 177 // wrong authorisation code len: request_len > 512 178 request[0] = BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE; 179 response = mock_att_service_write_callback(con_handle, bm_control_point_value_handle, ATT_TRANSACTION_MODE_NONE, 0, request, request_len); 180 CHECK_EQUAL(response, BOND_MANAGEMENT_OPERATION_FAILED); 181 } 182 183 184 // locally no (string empty), remote no (string empty) -> OK 185 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ln_empty_rn_empty){ 186 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, NULL, 187 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, NULL, 0); 188 } 189 190 // locally no (string exists), remote no (string empty) -> OK 191 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ln_exists_rn_empty){ 192 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "local_auth_str", 193 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, NULL, 0); 194 } 195 196 // locally no (string empty), remote yes (string exists) -> BOND_MANAGEMENT_CONTROL_POINT_OPCODE_NOT_SUPPORTED 197 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ln_empty_ry_exists){ 198 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "", 199 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "remote", 200 BOND_MANAGEMENT_CONTROL_POINT_OPCODE_NOT_SUPPORTED); 201 } 202 203 // locally no (string exists), remote yes (string exists) -> BOND_MANAGEMENT_CONTROL_POINT_OPCODE_NOT_SUPPORTED 204 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ln_exists_ry_exists){ 205 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "local_auth_str", 206 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "remote_auth_str", 207 BOND_MANAGEMENT_CONTROL_POINT_OPCODE_NOT_SUPPORTED); 208 } 209 210 // locally no (string exists), remote yes, (string exact) -> BOND_MANAGEMENT_CONTROL_POINT_OPCODE_NOT_SUPPORTED 211 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ln_exists_ry_exact){ 212 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "auth_str", 213 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "auth_str", 214 BOND_MANAGEMENT_CONTROL_POINT_OPCODE_NOT_SUPPORTED); 215 } 216 217 // locally yes (string empty), remote no (string empty) -> ATT_ERROR_INSUFFICIENT_AUTHORIZATION 218 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ly_empty_ry_empty){ 219 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE_WITH_AUTH, NULL, 220 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, NULL, 221 ATT_ERROR_INSUFFICIENT_AUTHORIZATION); 222 } 223 224 // locally yes (string exists), remote no (string empty) -> ATT_ERROR_INSUFFICIENT_AUTHORIZATION 225 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ly_exists_rn_empty){ 226 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE_WITH_AUTH, "local_auth_str", 227 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, NULL, 228 ATT_ERROR_INSUFFICIENT_AUTHORIZATION); 229 } 230 231 // locally yes (string exists), remote yes (string exists) -> ATT_ERROR_INSUFFICIENT_AUTHORIZATION 232 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ly_exists_ry_exists){ 233 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE_WITH_AUTH, "local_auth_str", 234 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "remote_auth_str", 235 ATT_ERROR_INSUFFICIENT_AUTHORIZATION); 236 } 237 238 // locally yes (string exists), remote yes, (string exact) -> OK 239 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ly_exists_ry_exact){ 240 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE_WITH_AUTH, "auth_str", 241 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "auth_str", 242 0); 243 } 244 245 // locally yes (string empty), remote yes (string exists) -> ATT_ERROR_INSUFFICIENT_AUTHORIZATION 246 TEST(BOND_MANAGEMENT_SERVICE_SERVER, write_control_point_ly_empty_ry_exists){ 247 validate_write_control_point(BMF_DELETE_ACTIVE_BOND_CLASSIC_AND_LE_WITH_AUTH, NULL, 248 BOND_MANAGEMENT_CMD_DELETE_ACTIVE_BOND_CLASSIC_AND_LE, "remote", 249 ATT_ERROR_INSUFFICIENT_AUTHORIZATION); 250 } 251 252 int main (int argc, const char * argv[]){ 253 return CommandLineTestRunner::RunAllTests(argc, argv); 254 } 255