1 #include "CppUTest/TestHarness.h" 2 #include "CppUTest/CommandLineTestRunner.h" 3 #include "CppUTestExt/MockSupport.h" 4 5 #include "classic/obex.h" 6 #include "classic/obex_parser.h" 7 #include "classic/obex_message_builder.h" 8 #include "btstack_util.h" 9 10 static const uint8_t flags = 1 << 1; 11 static const uint16_t maximum_obex_packet_length = 0xFFFF; 12 static const uint8_t obex_version_number = OBEX_VERSION; 13 static const uint8_t target[] = { 1, 2, 3, 4}; 14 15 // from parser_callback 16 static uint8_t test_header_id; 17 static uint8_t test_header_buffer[100]; 18 static uint16_t test_header_len; 19 20 // mock hci_dump.c 21 extern "C" void hci_dump_log(int log_level, const char * format, ...){} 22 23 static void parser_callback(void * user_data, uint8_t header_id, uint16_t total_len, uint16_t data_offset, const uint8_t * data_buffer, uint16_t data_len){ 24 if (obex_parser_header_store(test_header_buffer, sizeof(test_header_buffer), total_len, data_offset, data_buffer, data_len) == OBEX_PARSER_HEADER_COMPLETE){ 25 test_header_len = total_len; 26 test_header_id = header_id; 27 } 28 } 29 30 TEST_GROUP(OBEX_PARSER){ 31 obex_parser_t parser; 32 uint8_t message[300]; 33 34 void setup(void){ 35 test_header_id = 0; 36 test_header_len = 0; 37 } 38 void teardown(void){ 39 } 40 void parse_request(void){ 41 obex_parser_init_for_request(&parser, &parser_callback, NULL); 42 uint16_t message_len = big_endian_read_16(message, 1); 43 for (uint16_t i = 0; i < message_len - 1;i++){ 44 obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[i], 1); 45 CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INCOMPLETE, parser_state); 46 } 47 obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[message_len-1], 1); 48 CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_COMPLETE, parser_state); 49 } 50 void parse_response(uint8_t opcode){ 51 obex_parser_init_for_response(&parser, opcode, &parser_callback, NULL); 52 uint16_t message_len = big_endian_read_16(message, 1); 53 for (uint16_t i = 0; i < message_len - 1;i++){ 54 obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[i], 1); 55 CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INCOMPLETE, parser_state); 56 } 57 obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[message_len-1], 1); 58 CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_COMPLETE, parser_state); 59 } 60 }; 61 62 TEST(OBEX_PARSER, RequestOverrun){ 63 (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length); 64 uint16_t message_len = big_endian_read_16(message, 1); 65 for (uint16_t i = 0; i < message_len - 1;i++){ 66 obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[i], 1); 67 CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INCOMPLETE, parser_state); 68 } 69 obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[message_len-1], 1); 70 CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_COMPLETE, parser_state); 71 parser_state = obex_parser_process_data(&parser, &message[message_len], 1); 72 CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_OVERRUN, parser_state); 73 } 74 75 TEST(OBEX_PARSER, RequestInvalid){ 76 (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length); 77 // decrease packet len 78 uint16_t message_len = big_endian_read_16(message, 1) - 1; 79 big_endian_store_16(message, 1, message_len); 80 for (uint16_t i = 0; i < message_len;i++){ 81 obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[i], 1); 82 if (i < 2){ 83 CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INCOMPLETE, parser_state); 84 } else { 85 CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INVALID, parser_state); 86 } 87 } 88 } 89 90 TEST(OBEX_PARSER, ConnectRequest){ 91 (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length); 92 parse_request(); 93 obex_parser_operation_info_t op_info; 94 obex_parser_get_operation_info(&parser, &op_info); 95 CHECK_EQUAL(OBEX_OPCODE_CONNECT, op_info.opcode); 96 CHECK_EQUAL(obex_version_number, op_info.obex_version_number); 97 CHECK_EQUAL(flags, op_info.flags); 98 CHECK_EQUAL(maximum_obex_packet_length, op_info.max_packet_length); 99 } 100 101 TEST(OBEX_PARSER, ConnectRequestWithTarget){ 102 (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length); 103 (void) obex_message_builder_header_add_target(message, sizeof(message), target, sizeof(target)); 104 parse_request(); 105 obex_parser_operation_info_t op_info; 106 obex_parser_get_operation_info(&parser, &op_info); 107 CHECK_EQUAL(OBEX_HEADER_TARGET, test_header_id); 108 CHECK_EQUAL(sizeof(target), test_header_len); 109 MEMCMP_EQUAL(target, test_header_buffer, sizeof(target)); 110 } 111 112 TEST(OBEX_PARSER, ConnectResponse){ 113 // no create response yet, fake it 114 (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length); 115 message[0] = OBEX_RESP_SUCCESS; 116 parse_response(OBEX_OPCODE_CONNECT); 117 obex_parser_operation_info_t op_info; 118 obex_parser_get_operation_info(&parser, &op_info); 119 CHECK_EQUAL(OBEX_RESP_SUCCESS, op_info.response_code); 120 CHECK_EQUAL(obex_version_number, op_info.obex_version_number); 121 CHECK_EQUAL(flags, op_info.flags); 122 CHECK_EQUAL(maximum_obex_packet_length, op_info.max_packet_length); 123 } 124 125 TEST(OBEX_PARSER, GetResponseWithSRM){ 126 // no get response yet, fake it 127 (void) obex_message_builder_request_create_get(message, sizeof(message), 0x1234); 128 obex_message_builder_header_add_srm_enable(message, sizeof(message)); 129 parse_request(); 130 obex_parser_operation_info_t op_info; 131 obex_parser_get_operation_info(&parser, &op_info); 132 } 133 134 TEST(OBEX_PARSER, SetPathResponse){ 135 const uint8_t set_path_response_success[] = { 0xa0, 0x00, 0x03}; 136 memcpy(message, set_path_response_success, sizeof(set_path_response_success)); 137 parse_response(OBEX_OPCODE_SETPATH); 138 } 139 140 /** App Param Parser */ 141 142 static uint8_t test_tag_id; 143 static uint8_t test_tag_buffer[100]; 144 static uint16_t test_tag_len; 145 146 void app_param_parser_callback(void * user_data, uint8_t tag_id, uint8_t total_len, uint8_t data_offset, const uint8_t * data_buffer, uint8_t data_len){ 147 if (obex_app_param_parser_tag_store(test_header_buffer, sizeof(test_header_buffer), total_len, data_offset, data_buffer, data_len) == OBEX_APP_PARAM_PARSER_TAG_COMPLETE){ 148 test_tag_len = total_len; 149 test_tag_id = tag_id; 150 } 151 } 152 153 TEST_GROUP(APP_PARAM_PARSER){ 154 obex_app_param_parser_t parser; 155 void setup(void){ 156 test_tag_id = 0; 157 test_tag_len = 0; 158 } 159 void teardown(void){ 160 } 161 void parse_app_params(const uint8_t * app_params, uint8_t param_len){ 162 obex_app_param_parser_init(&parser, &app_param_parser_callback, param_len, NULL); 163 for (int i = 0; i < param_len - 1;i++){ 164 obex_app_param_parser_params_state_t parser_state = obex_app_param_parser_process_data(&parser, &app_params[i], 1); 165 CHECK_EQUAL(OBEX_APP_PARAM_PARSER_PARAMS_STATE_INCOMPLETE, parser_state); 166 } 167 if (param_len > 0){ 168 obex_app_param_parser_params_state_t parser_state = obex_app_param_parser_process_data(&parser, &app_params[param_len-1], 1); 169 CHECK_EQUAL(OBEX_APP_PARAM_PARSER_PARAMS_STATE_COMPLETE, parser_state); 170 } 171 } 172 }; 173 TEST(APP_PARAM_PARSER, EmptyParams){ 174 parse_app_params(NULL, 0); 175 CHECK_EQUAL(0, test_tag_id); 176 CHECK_EQUAL(0, test_tag_len); 177 } 178 179 TEST(APP_PARAM_PARSER, SingleParam){ 180 uint8_t message[] = { 0x01, 0x02, 0x03, 0x4}; 181 parse_app_params(message, sizeof(message)); 182 CHECK_EQUAL(1, test_tag_id); 183 CHECK_EQUAL(2, test_tag_len); 184 } 185 186 TEST(APP_PARAM_PARSER, Overrun){ 187 uint8_t message[] = { 0x01, 0x02, 0x03, 0x4}; 188 parse_app_params(message, sizeof(message)); 189 obex_app_param_parser_params_state_t parser_state = obex_app_param_parser_process_data(&parser, &message[0], 1); 190 CHECK_EQUAL(OBEX_APP_PARAM_PARSER_PARAMS_STATE_OVERRUN, parser_state); 191 CHECK_EQUAL(1, test_tag_id); 192 CHECK_EQUAL(2, test_tag_len); 193 } 194 195 TEST(APP_PARAM_PARSER, InvalidTagLen){ 196 uint8_t message[] = { 0x01, 0x04, 0x03, 0x4}; 197 obex_app_param_parser_t parser; 198 obex_app_param_parser_init(&parser, &app_param_parser_callback, sizeof(message), NULL); 199 obex_app_param_parser_params_state_t parser_state; 200 parser_state = obex_app_param_parser_process_data(&parser, &message[0], 1); 201 CHECK_EQUAL(OBEX_APP_PARAM_PARSER_PARAMS_STATE_INCOMPLETE, parser_state); 202 parser_state = obex_app_param_parser_process_data(&parser, &message[1], 1); 203 CHECK_EQUAL(OBEX_APP_PARAM_PARSER_PARAMS_STATE_INVALID, parser_state); 204 CHECK_EQUAL(0, test_tag_id); 205 CHECK_EQUAL(0, test_tag_len); 206 } 207 208 int main (int argc, const char * argv[]){ 209 return CommandLineTestRunner::RunAllTests(argc, argv); 210 } 211