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