xref: /btstack/test/obex/obex_parser_test.cpp (revision 077fecbb6ed539507f37505ebd8a5b00e01c55e9)
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 int main (int argc, const char * argv[]){
141     return CommandLineTestRunner::RunAllTests(argc, argv);
142 }
143