xref: /btstack/test/obex/obex_parser_test.cpp (revision ac9a0d84d5f7a715f496fcd8d0dd3b859de2f81a)
1*ac9a0d84SMatthias Ringwald #include "CppUTest/TestHarness.h"
2*ac9a0d84SMatthias Ringwald #include "CppUTest/CommandLineTestRunner.h"
3*ac9a0d84SMatthias Ringwald #include "CppUTestExt/MockSupport.h"
4*ac9a0d84SMatthias Ringwald 
5*ac9a0d84SMatthias Ringwald #include "classic/obex.h"
6*ac9a0d84SMatthias Ringwald #include "classic/obex_parser.h"
7*ac9a0d84SMatthias Ringwald #include "classic/obex_message_builder.h"
8*ac9a0d84SMatthias Ringwald #include "btstack_util.h"
9*ac9a0d84SMatthias Ringwald 
10*ac9a0d84SMatthias Ringwald static const uint8_t  flags = 1 << 1;
11*ac9a0d84SMatthias Ringwald static const uint16_t maximum_obex_packet_length = 0xFFFF;
12*ac9a0d84SMatthias Ringwald static const uint8_t  obex_version_number = OBEX_VERSION;
13*ac9a0d84SMatthias Ringwald static const uint8_t  target[] = { 1, 2, 3, 4};
14*ac9a0d84SMatthias Ringwald 
15*ac9a0d84SMatthias Ringwald // from parser_callback
16*ac9a0d84SMatthias Ringwald static uint8_t  test_header_id;
17*ac9a0d84SMatthias Ringwald static uint8_t  test_header_buffer[100];
18*ac9a0d84SMatthias Ringwald static uint16_t test_header_len;
19*ac9a0d84SMatthias Ringwald 
20*ac9a0d84SMatthias Ringwald // mock hci_dump.c
21*ac9a0d84SMatthias Ringwald extern "C" void hci_dump_log(int log_level, const char * format, ...){}
22*ac9a0d84SMatthias Ringwald 
23*ac9a0d84SMatthias 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){
24*ac9a0d84SMatthias 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){
25*ac9a0d84SMatthias Ringwald         test_header_len = total_len;
26*ac9a0d84SMatthias Ringwald         test_header_id  = header_id;
27*ac9a0d84SMatthias Ringwald     }
28*ac9a0d84SMatthias Ringwald }
29*ac9a0d84SMatthias Ringwald 
30*ac9a0d84SMatthias Ringwald TEST_GROUP(OBEX_PARSER){
31*ac9a0d84SMatthias Ringwald     obex_parser_t parser;
32*ac9a0d84SMatthias Ringwald     uint8_t  message[300];
33*ac9a0d84SMatthias Ringwald 
34*ac9a0d84SMatthias Ringwald     void setup(void){
35*ac9a0d84SMatthias Ringwald         test_header_id = 0;
36*ac9a0d84SMatthias Ringwald         test_header_len = 0;
37*ac9a0d84SMatthias Ringwald     }
38*ac9a0d84SMatthias Ringwald     void teardown(void){
39*ac9a0d84SMatthias Ringwald     }
40*ac9a0d84SMatthias Ringwald     void parse_request(void){
41*ac9a0d84SMatthias Ringwald         obex_parser_init_for_request(&parser, &parser_callback, NULL);
42*ac9a0d84SMatthias Ringwald         uint16_t message_len = big_endian_read_16(message, 1);
43*ac9a0d84SMatthias Ringwald         for (uint16_t i = 0; i < message_len - 1;i++){
44*ac9a0d84SMatthias Ringwald             obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[i], 1);
45*ac9a0d84SMatthias Ringwald             CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INCOMPLETE, parser_state);
46*ac9a0d84SMatthias Ringwald         }
47*ac9a0d84SMatthias Ringwald         obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[message_len-1], 1);
48*ac9a0d84SMatthias Ringwald         CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_COMPLETE, parser_state);
49*ac9a0d84SMatthias Ringwald     }
50*ac9a0d84SMatthias Ringwald     void parse_response(uint8_t opcode){
51*ac9a0d84SMatthias Ringwald         obex_parser_init_for_response(&parser, opcode, &parser_callback, NULL);
52*ac9a0d84SMatthias Ringwald         uint16_t message_len = big_endian_read_16(message, 1);
53*ac9a0d84SMatthias Ringwald         for (uint16_t i = 0; i < message_len - 1;i++){
54*ac9a0d84SMatthias Ringwald             obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[i], 1);
55*ac9a0d84SMatthias Ringwald             CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INCOMPLETE, parser_state);
56*ac9a0d84SMatthias Ringwald         }
57*ac9a0d84SMatthias Ringwald         obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[message_len-1], 1);
58*ac9a0d84SMatthias Ringwald         CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_COMPLETE, parser_state);
59*ac9a0d84SMatthias Ringwald     }
60*ac9a0d84SMatthias Ringwald };
61*ac9a0d84SMatthias Ringwald 
62*ac9a0d84SMatthias Ringwald TEST(OBEX_PARSER, RequestOverrun){
63*ac9a0d84SMatthias Ringwald     (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length);
64*ac9a0d84SMatthias Ringwald     uint16_t message_len = big_endian_read_16(message, 1);
65*ac9a0d84SMatthias Ringwald     for (uint16_t i = 0; i < message_len - 1;i++){
66*ac9a0d84SMatthias Ringwald         obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[i], 1);
67*ac9a0d84SMatthias Ringwald         CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INCOMPLETE, parser_state);
68*ac9a0d84SMatthias Ringwald     }
69*ac9a0d84SMatthias Ringwald     obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[message_len-1], 1);
70*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_COMPLETE, parser_state);
71*ac9a0d84SMatthias Ringwald     parser_state = obex_parser_process_data(&parser, &message[message_len], 1);
72*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_OVERRUN, parser_state);
73*ac9a0d84SMatthias Ringwald }
74*ac9a0d84SMatthias Ringwald 
75*ac9a0d84SMatthias Ringwald TEST(OBEX_PARSER, RequestInvalid){
76*ac9a0d84SMatthias Ringwald     (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length);
77*ac9a0d84SMatthias Ringwald     // decrease packet len
78*ac9a0d84SMatthias Ringwald     uint16_t message_len = big_endian_read_16(message, 1) - 1;
79*ac9a0d84SMatthias Ringwald     big_endian_store_16(message, 1, message_len);
80*ac9a0d84SMatthias Ringwald     for (uint16_t i = 0; i < message_len;i++){
81*ac9a0d84SMatthias Ringwald         obex_parser_object_state_t parser_state = obex_parser_process_data(&parser, &message[i], 1);
82*ac9a0d84SMatthias Ringwald         if (i < 2){
83*ac9a0d84SMatthias Ringwald             CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INCOMPLETE, parser_state);
84*ac9a0d84SMatthias Ringwald         } else {
85*ac9a0d84SMatthias Ringwald             CHECK_EQUAL(OBEX_PARSER_OBJECT_STATE_INVALID, parser_state);
86*ac9a0d84SMatthias Ringwald         }
87*ac9a0d84SMatthias Ringwald     }
88*ac9a0d84SMatthias Ringwald }
89*ac9a0d84SMatthias Ringwald 
90*ac9a0d84SMatthias Ringwald TEST(OBEX_PARSER, ConnectRequest){
91*ac9a0d84SMatthias Ringwald     (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length);
92*ac9a0d84SMatthias Ringwald     parse_request();
93*ac9a0d84SMatthias Ringwald     obex_parser_operation_info_t op_info;
94*ac9a0d84SMatthias Ringwald     obex_parser_get_operation_info(&parser, &op_info);
95*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(OBEX_OPCODE_CONNECT, op_info.opcode);
96*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(obex_version_number, op_info.obex_version_number);
97*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(flags, op_info.flags);
98*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(maximum_obex_packet_length, op_info.max_packet_length);
99*ac9a0d84SMatthias Ringwald }
100*ac9a0d84SMatthias Ringwald 
101*ac9a0d84SMatthias Ringwald TEST(OBEX_PARSER, ConnectRequestWithTarget){
102*ac9a0d84SMatthias Ringwald     (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length);
103*ac9a0d84SMatthias Ringwald     (void) obex_message_builder_header_add_target(message, sizeof(message), target, sizeof(target));
104*ac9a0d84SMatthias Ringwald     parse_request();
105*ac9a0d84SMatthias Ringwald     obex_parser_operation_info_t op_info;
106*ac9a0d84SMatthias Ringwald     obex_parser_get_operation_info(&parser, &op_info);
107*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(OBEX_HEADER_TARGET, test_header_id);
108*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(sizeof(target), test_header_len);
109*ac9a0d84SMatthias Ringwald     MEMCMP_EQUAL(target, test_header_buffer, sizeof(target));
110*ac9a0d84SMatthias Ringwald }
111*ac9a0d84SMatthias Ringwald 
112*ac9a0d84SMatthias Ringwald TEST(OBEX_PARSER, ConnectResponse){
113*ac9a0d84SMatthias Ringwald     // no create response yet, fake it
114*ac9a0d84SMatthias Ringwald     (void) obex_message_builder_request_create_connect(message, sizeof(message), obex_version_number, flags, maximum_obex_packet_length);
115*ac9a0d84SMatthias Ringwald     message[0] = OBEX_RESP_SUCCESS;
116*ac9a0d84SMatthias Ringwald     parse_response(OBEX_OPCODE_CONNECT);
117*ac9a0d84SMatthias Ringwald     obex_parser_operation_info_t op_info;
118*ac9a0d84SMatthias Ringwald     obex_parser_get_operation_info(&parser, &op_info);
119*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(OBEX_RESP_SUCCESS, op_info.response_code);
120*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(obex_version_number, op_info.obex_version_number);
121*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(flags, op_info.flags);
122*ac9a0d84SMatthias Ringwald     CHECK_EQUAL(maximum_obex_packet_length, op_info.max_packet_length);
123*ac9a0d84SMatthias Ringwald }
124*ac9a0d84SMatthias Ringwald 
125*ac9a0d84SMatthias Ringwald TEST(OBEX_PARSER, GetResponseWithSRM){
126*ac9a0d84SMatthias Ringwald     // no get response yet, fake it
127*ac9a0d84SMatthias Ringwald     (void) obex_message_builder_request_create_get(message, sizeof(message), 0x1234);
128*ac9a0d84SMatthias Ringwald     obex_message_builder_header_add_srm_enable(message, sizeof(message));
129*ac9a0d84SMatthias Ringwald     parse_request();
130*ac9a0d84SMatthias Ringwald     obex_parser_operation_info_t op_info;
131*ac9a0d84SMatthias Ringwald     obex_parser_get_operation_info(&parser, &op_info);
132*ac9a0d84SMatthias Ringwald }
133*ac9a0d84SMatthias Ringwald 
134*ac9a0d84SMatthias Ringwald TEST(OBEX_PARSER, SetPathResponse){
135*ac9a0d84SMatthias Ringwald     const uint8_t set_path_response_success[] = { 0xa0, 0x00, 0x03};
136*ac9a0d84SMatthias Ringwald     memcpy(message, set_path_response_success, sizeof(set_path_response_success));
137*ac9a0d84SMatthias Ringwald     parse_response(OBEX_OPCODE_SETPATH);
138*ac9a0d84SMatthias Ringwald }
139*ac9a0d84SMatthias Ringwald 
140*ac9a0d84SMatthias Ringwald int main (int argc, const char * argv[]){
141*ac9a0d84SMatthias Ringwald     return CommandLineTestRunner::RunAllTests(argc, argv);
142*ac9a0d84SMatthias Ringwald }
143