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