1 /* Make sure that all fields are freed in various scenarios. */ 2 3 #include <pb_decode.h> 4 #include <pb_encode.h> 5 #include <malloc_wrappers.h> 6 #include <stdio.h> 7 #include <test_helpers.h> 8 #include "mem_release.pb.h" 9 10 #define TEST(x) if (!(x)) { \ 11 fprintf(stderr, "Test " #x " on line %d failed.\n", __LINE__); \ 12 return false; \ 13 } 14 15 static char *test_str_arr[] = {"1", "2", ""}; 16 static SubMessage test_msg_arr[] = {SubMessage_init_zero, SubMessage_init_zero}; 17 static pb_extension_t ext1, ext2; 18 19 static void fill_TestMessage(TestMessage *msg) 20 { 21 msg->static_req_submsg.dynamic_str = "12345"; 22 msg->static_req_submsg.dynamic_str_arr_count = 3; 23 msg->static_req_submsg.dynamic_str_arr = test_str_arr; 24 msg->static_req_submsg.dynamic_submsg_count = 2; 25 msg->static_req_submsg.dynamic_submsg = test_msg_arr; 26 msg->static_req_submsg.dynamic_submsg[1].dynamic_str = "abc"; 27 msg->static_opt_submsg.dynamic_str = "abc"; 28 msg->static_rep_submsg_count = 2; 29 msg->static_rep_submsg[1].dynamic_str = "abc"; 30 msg->has_static_opt_submsg = true; 31 msg->dynamic_submsg = &msg->static_req_submsg; 32 33 msg->extensions = &ext1; 34 ext1.type = &dynamic_ext; 35 ext1.dest = &msg->static_req_submsg; 36 ext1.next = &ext2; 37 ext2.type = &static_ext; 38 ext2.dest = &msg->static_req_submsg; 39 ext2.next = NULL; 40 } 41 42 /* Basic fields, nested submessages, extensions */ 43 static bool test_TestMessage() 44 { 45 uint8_t buffer[256]; 46 size_t msgsize; 47 48 /* Construct a message with various fields filled in */ 49 { 50 TestMessage msg = TestMessage_init_zero; 51 pb_ostream_t stream; 52 53 fill_TestMessage(&msg); 54 55 stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); 56 if (!pb_encode(&stream, TestMessage_fields, &msg)) 57 { 58 fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream)); 59 return false; 60 } 61 msgsize = stream.bytes_written; 62 } 63 64 /* Output encoded message for debug */ 65 SET_BINARY_MODE(stdout); 66 fwrite(buffer, 1, msgsize, stdout); 67 68 /* Decode memory using dynamic allocation */ 69 { 70 TestMessage msg = TestMessage_init_zero; 71 pb_istream_t stream; 72 SubMessage ext2_dest; 73 74 msg.extensions = &ext1; 75 ext1.type = &dynamic_ext; 76 ext1.dest = NULL; 77 ext1.next = &ext2; 78 ext2.type = &static_ext; 79 ext2.dest = &ext2_dest; 80 ext2.next = NULL; 81 82 stream = pb_istream_from_buffer(buffer, msgsize); 83 if (!pb_decode(&stream, TestMessage_fields, &msg)) 84 { 85 fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&stream)); 86 return false; 87 } 88 89 /* Make sure it encodes back to same data */ 90 { 91 uint8_t buffer2[256]; 92 pb_ostream_t ostream = pb_ostream_from_buffer(buffer2, sizeof(buffer2)); 93 TEST(pb_encode(&ostream, TestMessage_fields, &msg)); 94 TEST(ostream.bytes_written == msgsize); 95 TEST(memcmp(buffer, buffer2, msgsize) == 0); 96 } 97 98 /* Make sure that malloc counters work */ 99 TEST(get_alloc_count() > 0); 100 101 /* Make sure that pb_release releases everything */ 102 pb_release(TestMessage_fields, &msg); 103 TEST(get_alloc_count() == 0); 104 105 /* Check that double-free is a no-op */ 106 pb_release(TestMessage_fields, &msg); 107 TEST(get_alloc_count() == 0); 108 } 109 110 return true; 111 } 112 113 /* Oneofs */ 114 static bool test_OneofMessage() 115 { 116 uint8_t buffer[256]; 117 size_t msgsize; 118 119 { 120 pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); 121 122 /* Encode first with TestMessage */ 123 { 124 OneofMessage msg = OneofMessage_init_zero; 125 msg.which_msgs = OneofMessage_msg1_tag; 126 127 fill_TestMessage(&msg.msgs.msg1); 128 129 if (!pb_encode(&stream, OneofMessage_fields, &msg)) 130 { 131 fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream)); 132 return false; 133 } 134 } 135 136 /* Encode second with SubMessage, invoking 'merge' behaviour */ 137 { 138 OneofMessage msg = OneofMessage_init_zero; 139 msg.which_msgs = OneofMessage_msg2_tag; 140 141 msg.first = 999; 142 msg.msgs.msg2.dynamic_str = "ABCD"; 143 msg.last = 888; 144 145 if (!pb_encode(&stream, OneofMessage_fields, &msg)) 146 { 147 fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream)); 148 return false; 149 } 150 } 151 msgsize = stream.bytes_written; 152 } 153 154 { 155 OneofMessage msg = OneofMessage_init_zero; 156 pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize); 157 if (!pb_decode(&stream, OneofMessage_fields, &msg)) 158 { 159 fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&stream)); 160 return false; 161 } 162 163 TEST(msg.first == 999); 164 TEST(msg.which_msgs == OneofMessage_msg2_tag); 165 TEST(msg.msgs.msg2.dynamic_str); 166 TEST(strcmp(msg.msgs.msg2.dynamic_str, "ABCD") == 0); 167 TEST(msg.msgs.msg2.dynamic_str_arr == NULL); 168 TEST(msg.msgs.msg2.dynamic_submsg == NULL); 169 TEST(msg.last == 888); 170 171 pb_release(OneofMessage_fields, &msg); 172 TEST(get_alloc_count() == 0); 173 pb_release(OneofMessage_fields, &msg); 174 TEST(get_alloc_count() == 0); 175 } 176 177 return true; 178 } 179 180 int main() 181 { 182 if (test_TestMessage() && test_OneofMessage()) 183 return 0; 184 else 185 return 1; 186 } 187 188