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