LCOV - code coverage report
Current view: top level - mem_release - mem_release.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 108 123 87.8 %
Date: 2023-02-14 20:10:26 Functions: 5 6 83.3 %

          Line data    Source code
       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 %s on line %d failed.\n", #x, __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           2 : static void fill_TestMessage(TestMessage *msg)
      20             : {
      21           2 :     msg->static_req_submsg.dynamic_str = "12345";
      22           2 :     msg->static_req_submsg.dynamic_str_arr_count = 3;
      23           2 :     msg->static_req_submsg.dynamic_str_arr = test_str_arr;
      24           2 :     msg->static_req_submsg.dynamic_submsg_count = 2;
      25           2 :     msg->static_req_submsg.dynamic_submsg = test_msg_arr;
      26           2 :     msg->static_req_submsg.dynamic_submsg[1].dynamic_str = "abc";
      27           2 :     msg->static_opt_submsg.dynamic_str = "abc";
      28           2 :     msg->static_rep_submsg_count = 2;
      29           2 :     msg->static_rep_submsg[1].dynamic_str = "abc";
      30           2 :     msg->has_static_opt_submsg = true;
      31           2 :     msg->dynamic_submsg = &msg->static_req_submsg;
      32             : 
      33           2 :     msg->extensions = &ext1;
      34           2 :     ext1.type = &dynamic_ext;
      35           2 :     ext1.dest = &msg->static_req_submsg;
      36           2 :     ext1.next = &ext2;
      37           2 :     ext2.type = &static_ext;
      38           2 :     ext2.dest = &msg->static_req_submsg;
      39           2 :     ext2.next = NULL;
      40           2 : }
      41             : 
      42             : /* Basic fields, nested submessages, extensions */
      43           1 : 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           1 :         TestMessage msg = TestMessage_init_zero;
      51             :         pb_ostream_t stream;
      52             : 
      53           1 :         fill_TestMessage(&msg);
      54             :         
      55           1 :         stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
      56           1 :         if (!pb_encode(&stream, TestMessage_fields, &msg))
      57             :         {
      58           0 :             fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream));
      59           0 :             return false;
      60             :         }
      61           1 :         msgsize = stream.bytes_written;
      62             :     }
      63             :     
      64             :     /* Output encoded message for debug */
      65             :     SET_BINARY_MODE(stdout);
      66           1 :     fwrite(buffer, 1, msgsize, stdout);
      67             :     
      68             :     /* Decode memory using dynamic allocation */
      69             :     {
      70           1 :         TestMessage msg = TestMessage_init_zero;
      71             :         pb_istream_t stream;
      72             :         SubMessage ext2_dest;
      73             : 
      74           1 :         msg.extensions = &ext1;
      75           1 :         ext1.type = &dynamic_ext;
      76           1 :         ext1.dest = NULL;
      77           1 :         ext1.next = &ext2;
      78           1 :         ext2.type = &static_ext;
      79           1 :         ext2.dest = &ext2_dest;
      80           1 :         ext2.next = NULL;
      81             :         
      82           1 :         stream = pb_istream_from_buffer(buffer, msgsize);
      83           1 :         if (!pb_decode(&stream, TestMessage_fields, &msg))
      84             :         {
      85           0 :             fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&stream));
      86           0 :             return false;
      87             :         }
      88             :         
      89             :         /* Make sure it encodes back to same data */
      90             :         {
      91             :             uint8_t buffer2[256];
      92           1 :             pb_ostream_t ostream = pb_ostream_from_buffer(buffer2, sizeof(buffer2));
      93           1 :             TEST(pb_encode(&ostream, TestMessage_fields, &msg));
      94           1 :             TEST(ostream.bytes_written == msgsize);
      95           1 :             TEST(memcmp(buffer, buffer2, msgsize) == 0);
      96             :         }
      97             :         
      98             :         /* Make sure that malloc counters work */
      99           1 :         TEST(get_alloc_count() > 0);
     100             :         
     101             :         /* Make sure that pb_release releases everything */
     102           1 :         pb_release(TestMessage_fields, &msg);
     103           1 :         TEST(get_alloc_count() == 0);
     104             :         
     105             :         /* Check that double-free is a no-op */
     106           1 :         pb_release(TestMessage_fields, &msg);
     107           1 :         TEST(get_alloc_count() == 0);
     108             :     }
     109             :     
     110           1 :     return true;
     111             : }
     112             : 
     113             : /* Oneofs */
     114           1 : static bool test_OneofMessage()
     115             : {
     116             :     uint8_t buffer[256];
     117             :     size_t msgsize;
     118             : 
     119             :     {
     120           1 :         pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
     121             : 
     122             :         /* Encode first with TestMessage */
     123             :         {
     124           1 :             OneofMessage msg = OneofMessage_init_zero;
     125           1 :             msg.which_msgs = OneofMessage_msg1_tag;
     126             : 
     127           1 :             fill_TestMessage(&msg.msgs.msg1);
     128             : 
     129           1 :             if (!pb_encode(&stream, OneofMessage_fields, &msg))
     130             :             {
     131           0 :                 fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream));
     132           0 :                 return false;
     133             :             }
     134             :         }
     135             : 
     136             :         /* Encode second with SubMessage, replacing the oneof item */
     137             :         {
     138           1 :             OneofMessage msg = OneofMessage_init_zero;
     139           1 :             char *teststr = "1";
     140           1 :             msg.which_msgs = OneofMessage_msg2_tag;
     141             : 
     142           1 :             msg.first = 999;
     143           1 :             msg.msgs.msg2.dynamic_str = "ABCD";
     144           1 :             msg.msgs.msg2.dynamic_str_arr_count = 1;
     145           1 :             msg.msgs.msg2.dynamic_str_arr = &teststr;
     146           1 :             msg.last = 888;
     147             : 
     148           1 :             if (!pb_encode(&stream, OneofMessage_fields, &msg))
     149             :             {
     150           0 :                 fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream));
     151           0 :                 return false;
     152             :             }
     153             :         }
     154             : 
     155             :         /* Encode second SubMessage, invoking submessage merge behavior */
     156             :         {
     157           1 :             OneofMessage msg = OneofMessage_init_zero;
     158           1 :             char *teststr = "2";
     159           1 :             msg.which_msgs = OneofMessage_msg2_tag;
     160             : 
     161           1 :             msg.first = 99;
     162           1 :             msg.msgs.msg2.dynamic_str = "EFGH";
     163           1 :             msg.msgs.msg2.dynamic_str_arr_count = 1;
     164           1 :             msg.msgs.msg2.dynamic_str_arr = &teststr;
     165           1 :             msg.last = 88;
     166             : 
     167           1 :             if (!pb_encode(&stream, OneofMessage_fields, &msg))
     168             :             {
     169           0 :                 fprintf(stderr, "Encode failed: %s\n", PB_GET_ERROR(&stream));
     170           0 :                 return false;
     171             :             }
     172             :         }
     173           1 :         msgsize = stream.bytes_written;
     174             :     }
     175             : 
     176             :     {
     177           1 :         OneofMessage msg = OneofMessage_init_zero;
     178           1 :         pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
     179           1 :         if (!pb_decode(&stream, OneofMessage_fields, &msg))
     180             :         {
     181           0 :             fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&stream));
     182           0 :             return false;
     183             :         }
     184             : 
     185           1 :         TEST(msg.first == 99);
     186           1 :         TEST(msg.which_msgs == OneofMessage_msg2_tag);
     187           1 :         TEST(msg.msgs.msg2.dynamic_str);
     188           1 :         TEST(strcmp(msg.msgs.msg2.dynamic_str, "EFGH") == 0);
     189           1 :         TEST(msg.msgs.msg2.dynamic_str_arr != NULL);
     190           1 :         TEST(msg.msgs.msg2.dynamic_str_arr_count == 2);
     191           1 :         TEST(strcmp(msg.msgs.msg2.dynamic_str_arr[0], "1") == 0);
     192           1 :         TEST(strcmp(msg.msgs.msg2.dynamic_str_arr[1], "2") == 0);
     193           1 :         TEST(msg.msgs.msg2.dynamic_submsg == NULL);
     194           1 :         TEST(msg.last == 88);
     195             : 
     196           1 :         pb_release(OneofMessage_fields, &msg);
     197           1 :         TEST(get_alloc_count() == 0);
     198           1 :         pb_release(OneofMessage_fields, &msg);
     199           1 :         TEST(get_alloc_count() == 0);
     200             :     }
     201             : 
     202           1 :     return true;
     203             : }
     204             : 
     205           0 : static bool dummy_decode_cb(pb_istream_t *stream, const pb_field_t *field, void **arg)
     206             : {
     207           0 :     return false;
     208             : }
     209             : 
     210             : /* Garbage input */
     211           1 : static bool test_Garbage()
     212             : {
     213           1 :     const uint8_t buffer[] = "I'm only happy when it rains";
     214           1 :     const size_t msgsize = sizeof(buffer);
     215             : 
     216             :     {
     217           1 :         OneofMessage msg = OneofMessage_init_zero;
     218           1 :         pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
     219           1 :         TEST(!pb_decode(&stream, OneofMessage_fields, &msg));
     220             :     }
     221             : 
     222             :     {
     223           1 :         TestMessage msg = TestMessage_init_zero;
     224           1 :         pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
     225           1 :         TEST(!pb_decode(&stream, TestMessage_fields, &msg));
     226             :     }
     227             : 
     228             :     {
     229           1 :         RepeatedMessage msg = RepeatedMessage_init_zero;
     230           1 :         pb_istream_t stream = pb_istream_from_buffer(buffer, msgsize);
     231           1 :         msg.subs.arg = NULL;
     232           1 :         msg.subs.funcs.decode = dummy_decode_cb;
     233           1 :         TEST(!pb_decode(&stream, RepeatedMessage_fields, &msg));
     234             :     }
     235             : 
     236           1 :     return true;
     237             : }
     238             : 
     239           1 : int main()
     240             : {
     241           1 :     if (test_TestMessage() && test_OneofMessage() && test_Garbage())
     242           1 :         return 0;
     243             :     else
     244           0 :         return 1;
     245             : }
     246             : 

Generated by: LCOV version 1.14