xref: /btstack/test/gatt_service_server/bond_management_service_server_test.cpp (revision 761810140b45afcf72e5e9ae0d74d4328826cec7)
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
gap_delete_bonding(bd_addr_type_t address_type,bd_addr_t address)32 void gap_delete_bonding(bd_addr_type_t address_type, bd_addr_t address){
33     // traack call if needed
34 }
gap_drop_link_key_for_bd_addr(bd_addr_t addr)35 void gap_drop_link_key_for_bd_addr(bd_addr_t addr){
36     // traack call if needed
37 }
gap_link_key_iterator_init(btstack_link_key_iterator_t * it)38 int gap_link_key_iterator_init(btstack_link_key_iterator_t * it){
39     return 1;
40 }
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)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 }
gap_link_key_iterator_done(btstack_link_key_iterator_t * it)45 void gap_link_key_iterator_done(btstack_link_key_iterator_t * it){
46 }
47 static hci_connection_t test_connection;
hci_connection_for_handle(hci_con_handle_t con_handle)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 }
le_device_db_max_count(void)53 int le_device_db_max_count(void){
54     return 0;
55 }
le_device_db_info(int index,int * addr_type,bd_addr_t addr,sm_key_t irk)56 void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk){
57 }
58 //
59 
TEST_GROUP(BOND_MANAGEMENT_SERVICE_SERVER)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 
TEST(BOND_MANAGEMENT_SERVICE_SERVER,lookup_attribute_handles)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 
TEST(BOND_MANAGEMENT_SERVICE_SERVER,read_bm_features_value0)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 
TEST(BOND_MANAGEMENT_SERVICE_SERVER,read_bm_features_value1)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 
TEST(BOND_MANAGEMENT_SERVICE_SERVER,read_bm_features_value2)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 
TEST(BOND_MANAGEMENT_SERVICE_SERVER,read_bm_features_value3)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 
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_bm_control_point_0)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ln_empty_rn_empty)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ln_exists_rn_empty)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ln_empty_ry_exists)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ln_exists_ry_exists)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ln_exists_ry_exact)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ly_empty_ry_empty)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ly_exists_rn_empty)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ly_exists_ry_exists)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ly_exists_ry_exact)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
TEST(BOND_MANAGEMENT_SERVICE_SERVER,write_control_point_ly_empty_ry_exists)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 
main(int argc,const char * argv[])252 int main (int argc, const char * argv[]){
253     return CommandLineTestRunner::RunAllTests(argc, argv);
254 }
255