Home | History | Annotate | Download | only in mem_release
      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