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
hci_dump_log(int log_level,const char * format,...)21 extern "C" void hci_dump_log(int log_level, const char * format, ...){}
22
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)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
TEST_GROUP(OBEX_PARSER)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
TEST(OBEX_PARSER,RequestOverrun)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
TEST(OBEX_PARSER,RequestInvalid)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
TEST(OBEX_PARSER,ConnectRequest)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
TEST(OBEX_PARSER,ConnectRequestWithTarget)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
TEST(OBEX_PARSER,ConnectResponse)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
TEST(OBEX_PARSER,GetResponseWithSRM)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
TEST(OBEX_PARSER,SetPathResponse)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
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)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
TEST_GROUP(APP_PARAM_PARSER)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 };
TEST(APP_PARAM_PARSER,EmptyParams)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
TEST(APP_PARAM_PARSER,SingleParam)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
TEST(APP_PARAM_PARSER,Overrun)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
TEST(APP_PARAM_PARSER,InvalidTagLen)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
main(int argc,const char * argv[])208 int main (int argc, const char * argv[]){
209 return CommandLineTestRunner::RunAllTests(argc, argv);
210 }
211