LCOV - code coverage report
Current view: top level - alltypes_proto3_callback - decode_alltypes_callback.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 203 220 92.3 %
Date: 2023-02-14 20:10:26 Functions: 18 18 100.0 %

          Line data    Source code
       1             : /* Attempts to test all the datatypes supported by ProtoBuf when used as callback fields.
       2             :  * Note that normally there would be no reason to use callback fields for this,
       3             :  * because each encoder defined here only gives a single field.
       4             :  */
       5             : 
       6             : #include <stdio.h>
       7             : #include <string.h>
       8             : #include <stdlib.h>
       9             : #include <pb_decode.h>
      10             : #include "alltypes.pb.h"
      11             : #include "test_helpers.h"
      12             : 
      13             : #define TEST(x) if (!(x)) { \
      14             :     printf("Test %s failed (in field %d).\n", #x, field->tag); \
      15             :     return false; \
      16             :     }
      17             : 
      18           8 : static bool read_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
      19             : {
      20             :     uint64_t value;
      21           8 :     if (!pb_decode_varint(stream, &value))
      22           0 :         return false;
      23             :     
      24           8 :     TEST((int64_t)value == (intptr_t)*arg);
      25           8 :     return true;
      26             : }
      27             : 
      28           2 : static bool read_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
      29             : {
      30             :     int64_t value;
      31           2 :     if (!pb_decode_svarint(stream, &value))
      32           0 :         return false;
      33             :     
      34           2 :     TEST(value == (intptr_t)*arg);
      35           2 :     return true;
      36             : }
      37             : 
      38           3 : static bool read_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
      39             : {
      40             :     uint32_t value;
      41           3 :     if (!pb_decode_fixed32(stream, &value))
      42           0 :         return false;
      43             :     
      44           3 :     TEST(value == *(uint32_t*)*arg);
      45           3 :     return true;
      46             : }
      47             : 
      48           2 : static bool read_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
      49             : {
      50             :     uint64_t value;
      51           2 :     if (!pb_decode_fixed64(stream, &value))
      52           0 :         return false;
      53             :     
      54           2 :     TEST(value == *(uint64_t*)*arg);
      55           2 :     return true;
      56             : }
      57             : 
      58           1 : static bool read_double(pb_istream_t *stream, const pb_field_t *field, void **arg)
      59             : {
      60             : #ifdef PB_CONVERT_DOUBLE_FLOAT
      61             :     if (sizeof(double) == sizeof(float))
      62             :     {
      63             :         float value;
      64             :         if (!pb_decode_double_as_float(stream, &value))
      65             :             return false;
      66             :         
      67             :         TEST(memcmp(&value, *arg, sizeof(float)) == 0);
      68             :         return true;
      69             :     }
      70             : #endif
      71             : 
      72             :     uint64_t value;
      73           1 :     if (!pb_decode_fixed64(stream, &value))
      74           0 :         return false;
      75             :     
      76           1 :     TEST(value == *(uint64_t*)*arg);
      77           1 :     return true;
      78             : }
      79             : 
      80           2 : static bool read_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
      81             : {
      82           2 :     uint8_t buf[16] = {0};
      83           2 :     size_t len = stream->bytes_left;
      84             :     
      85           2 :     if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
      86           0 :         return false;
      87             :     
      88           2 :     TEST(strcmp((char*)buf, *arg) == 0);
      89           2 :     return true;
      90             : }
      91             : 
      92           2 : static bool read_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
      93             : {
      94           2 :     SubMessage submsg = {""};
      95           2 :     SubMessage *ref = *arg;
      96             :     
      97           2 :     if (!pb_decode(stream, SubMessage_fields, &submsg))
      98           0 :         return false;
      99             :     
     100           2 :     TEST(strcmp(submsg.substuff1, ref->substuff1) == 0);
     101           2 :     TEST(submsg.substuff2 == ref->substuff2);
     102           2 :     TEST(submsg.substuff3 == ref->substuff3); 
     103           2 :     return true;
     104             : }
     105             : 
     106          11 : static bool read_emptymsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
     107             : {
     108          11 :     EmptyMessage emptymsg = {0};
     109          11 :     return pb_decode(stream, EmptyMessage_fields, &emptymsg);
     110             : }
     111             : 
     112          60 : static bool read_repeated_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
     113             : {
     114          60 :     int32_t** expected = (int32_t**)arg;
     115             :     uint64_t value;
     116          60 :     if (!pb_decode_varint(stream, &value))
     117           0 :         return false;
     118             : 
     119          60 :     TEST(*(*expected)++ == value);
     120          60 :     return true;
     121             : }
     122             : 
     123          20 : static bool read_repeated_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
     124             : {
     125          20 :     int32_t** expected = (int32_t**)arg;
     126             :     int64_t value;
     127          20 :     if (!pb_decode_svarint(stream, &value))
     128           0 :         return false;
     129             : 
     130          20 :     TEST(*(*expected)++ == value);
     131          20 :     return true;
     132             : }
     133             : 
     134          30 : static bool read_repeated_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
     135             : {
     136          30 :     uint32_t** expected = (uint32_t**)arg;
     137             :     uint32_t value;
     138          30 :     if (!pb_decode_fixed32(stream, &value))
     139           0 :         return false;
     140             : 
     141          30 :     TEST(*(*expected)++ == value);
     142          30 :     return true;
     143             : }
     144             : 
     145          20 : static bool read_repeated_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
     146             : {
     147          20 :     uint64_t** expected = (uint64_t**)arg;
     148             :     uint64_t value;
     149          20 :     if (!pb_decode_fixed64(stream, &value))
     150           0 :         return false;
     151             : 
     152          20 :     TEST(*(*expected)++ == value);
     153          20 :     return true;
     154             : }
     155             : 
     156          10 : static bool read_repeated_double(pb_istream_t *stream, const pb_field_t *field, void **arg)
     157             : {
     158             : #ifdef PB_CONVERT_DOUBLE_FLOAT
     159             :     if (sizeof(double) == sizeof(float))
     160             :     {
     161             :         float** expectedf = (float**)arg;
     162             :         float value;
     163             :         if (!pb_decode_double_as_float(stream, &value))
     164             :             return false;
     165             :         
     166             :         TEST(memcmp(&value, (*expectedf)++, sizeof(float)) == 0);
     167             :         return true;
     168             :     }
     169             : #endif
     170             : 
     171          10 :     uint64_t** expected = (uint64_t**)arg;
     172             :     uint64_t value;
     173          10 :     if (!pb_decode_fixed64(stream, &value))
     174           0 :         return false;
     175             : 
     176          10 :     TEST(*(*expected)++ == value);
     177          10 :     return true;
     178             : }
     179             : 
     180          20 : static bool read_repeated_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
     181             : {
     182          20 :     uint8_t*** expected = (uint8_t***)arg;
     183          20 :     uint8_t buf[16] = {0};
     184          20 :     size_t len = stream->bytes_left;
     185             :     
     186          20 :     if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
     187           0 :         return false;
     188             :     
     189          20 :     TEST(strcmp((char*)*(*expected)++, (char*)buf) == 0);
     190          20 :     return true;
     191             : }
     192             : 
     193          10 : static bool read_repeated_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
     194             : {
     195          10 :     SubMessage** expected = (SubMessage**)arg;
     196          10 :     SubMessage submsg = {""};
     197          10 :     if (!pb_decode(stream, SubMessage_fields, &submsg))
     198           0 :         return false;
     199             : 
     200          10 :     TEST(strcmp(submsg.substuff1, (*expected)->substuff1) == 0);
     201          10 :     TEST(submsg.substuff2 == (*expected)->substuff2);
     202          10 :     TEST(submsg.substuff3 == (*expected)->substuff3);
     203          10 :     (*expected)++;
     204             : 
     205          10 :     return true;
     206             : }
     207             : 
     208           2 : static bool read_limits(pb_istream_t *stream, const pb_field_t *field, void **arg)
     209             : {
     210           2 :     Limits decoded = {0};
     211           2 :     if (!pb_decode(stream, Limits_fields, &decoded))
     212           0 :         return false;
     213             : 
     214           2 :     TEST(decoded.int32_min  == INT32_MIN);
     215           2 :     TEST(decoded.int32_max  == INT32_MAX);
     216           2 :     TEST(decoded.uint32_min == 0);
     217           2 :     TEST(decoded.uint32_max == UINT32_MAX);
     218           2 :     TEST(decoded.int64_min  == INT64_MIN);
     219           2 :     TEST(decoded.int64_max  == INT64_MAX);
     220           2 :     TEST(decoded.uint64_min == 0);
     221           2 :     TEST(decoded.uint64_max == UINT64_MAX);
     222           2 :     TEST(decoded.enum_min   == HugeEnum_Negative);
     223           2 :     TEST(decoded.enum_max   == HugeEnum_Positive);
     224             :     
     225           2 :     return true;
     226             : }
     227             : 
     228             : /* This function is called once from main(), it handles
     229             :    the decoding and checks the fields. */
     230           2 : bool check_alltypes(pb_istream_t *stream, int mode)
     231             : {
     232             :     /* Values for use from callbacks through pointers. */
     233             :     bool status;
     234             :     
     235           2 :     int32_t     rep_int32[5]    = {0, 0, 0, 0, -2001};
     236           2 :     int32_t     rep_int64[5]    = {0, 0, 0, 0, -2002};
     237           2 :     int32_t     rep_uint32[5]   = {0, 0, 0, 0,  2003};
     238           2 :     int32_t     rep_uint64[5]   = {0, 0, 0, 0,  2004};
     239           2 :     int32_t     rep_sint32[5]   = {0, 0, 0, 0, -2005};
     240           2 :     int32_t     rep_sint64[5]   = {0, 0, 0, 0, -2006};
     241           2 :     int32_t     rep_bool[5]     = {false, false, false, false, true};
     242           2 :     uint32_t    rep_fixed32[5]  = {0, 0, 0, 0,  2008};
     243           2 :     int32_t     rep_sfixed32[5] = {0, 0, 0, 0, -2009};
     244           2 :     float       rep_float[5]    = {0, 0, 0, 0,  2010.0f};
     245           2 :     uint64_t    rep_fixed64[5]  = {0, 0, 0, 0,  2011};
     246           2 :     int64_t     rep_sfixed64[5] = {0, 0, 0, 0, -2012};
     247           2 :     double      rep_double[5]   = {0, 0, 0, 0,  2013.0};
     248           2 :     char*       rep_string[5]   = {"", "", "", "", "2014"};
     249           2 :     char*       rep_bytes[5]    = {"", "", "", "", "2015"};
     250           2 :     SubMessage  rep_submsg[5]   = {{"", 0, 0},
     251             :                                    {"", 0, 0},
     252             :                                    {"", 0, 0},
     253             :                                    {"", 0, 0},
     254             :                                    {"2016", 2016, 2016}};
     255           2 :     int32_t     rep_enum[5]     = {0, 0, 0, 0, MyEnum_Truth};
     256             :     
     257           2 :     uint32_t    sng_fixed32     = 3048;
     258           2 :     int32_t     sng_sfixed32    = 3049;
     259           2 :     float       sng_float       = 3050.0f;
     260           2 :     uint64_t    sng_fixed64     = 3051;
     261           2 :     int64_t     sng_sfixed64    = 3052;
     262           2 :     double      sng_double      = 3053.0f;
     263           2 :     SubMessage  sng_submsg      = {"3056", 3056};
     264             : 
     265           2 :     SubMessage  oneof_msg1      = {"4059", 4059};
     266             :     
     267           2 :     AllTypes alltypes = AllTypes_init_zero;
     268             : 
     269             :     /* Bind callbacks for repeated fields */
     270           2 :     alltypes.rep_int32.funcs.decode = &read_repeated_varint;
     271           2 :     alltypes.rep_int32.arg = rep_int32;
     272             :     
     273           2 :     alltypes.rep_int64.funcs.decode = &read_repeated_varint;
     274           2 :     alltypes.rep_int64.arg = rep_int64;
     275             :     
     276           2 :     alltypes.rep_uint32.funcs.decode = &read_repeated_varint;
     277           2 :     alltypes.rep_uint32.arg = rep_uint32;
     278             :     
     279           2 :     alltypes.rep_uint64.funcs.decode = &read_repeated_varint;
     280           2 :     alltypes.rep_uint64.arg = rep_uint64;
     281             :     
     282           2 :     alltypes.rep_sint32.funcs.decode = &read_repeated_svarint;
     283           2 :     alltypes.rep_sint32.arg = rep_sint32;
     284             :     
     285           2 :     alltypes.rep_sint64.funcs.decode = &read_repeated_svarint;
     286           2 :     alltypes.rep_sint64.arg = rep_sint64;
     287             :     
     288           2 :     alltypes.rep_bool.funcs.decode = &read_repeated_varint;
     289           2 :     alltypes.rep_bool.arg = rep_bool;
     290             :     
     291           2 :     alltypes.rep_fixed32.funcs.decode = &read_repeated_fixed32;
     292           2 :     alltypes.rep_fixed32.arg = rep_fixed32;
     293             :     
     294           2 :     alltypes.rep_sfixed32.funcs.decode = &read_repeated_fixed32;
     295           2 :     alltypes.rep_sfixed32.arg = rep_sfixed32;
     296             :     
     297           2 :     alltypes.rep_float.funcs.decode = &read_repeated_fixed32;
     298           2 :     alltypes.rep_float.arg = rep_float;
     299             :     
     300           2 :     alltypes.rep_fixed64.funcs.decode = &read_repeated_fixed64;
     301           2 :     alltypes.rep_fixed64.arg = rep_fixed64;
     302             :     
     303           2 :     alltypes.rep_sfixed64.funcs.decode = &read_repeated_fixed64;
     304           2 :     alltypes.rep_sfixed64.arg = rep_sfixed64;
     305             :     
     306           2 :     alltypes.rep_double.funcs.decode = &read_repeated_double;
     307           2 :     alltypes.rep_double.arg = rep_double;
     308             :     
     309           2 :     alltypes.rep_string.funcs.decode = &read_repeated_string;
     310           2 :     alltypes.rep_string.arg = rep_string;
     311             :     
     312           2 :     alltypes.rep_bytes.funcs.decode = &read_repeated_string;
     313           2 :     alltypes.rep_bytes.arg = rep_bytes;
     314             :     
     315           2 :     alltypes.rep_submsg.funcs.decode = &read_repeated_submsg;
     316           2 :     alltypes.rep_submsg.arg = rep_submsg;
     317             :     
     318           2 :     alltypes.rep_enum.funcs.decode = &read_repeated_varint;
     319           2 :     alltypes.rep_enum.arg = rep_enum;
     320             :     
     321           2 :     alltypes.rep_emptymsg.funcs.decode = &read_emptymsg;
     322             :     
     323           2 :     alltypes.req_limits.funcs.decode = &read_limits;
     324             :     
     325           2 :     alltypes.end.funcs.decode = &read_varint;
     326           2 :     alltypes.end.arg = (void*)1099;
     327             :     
     328             :     /* Bind callbacks for optional fields */
     329           2 :     if (mode == 1)
     330             :     {
     331           1 :         alltypes.sng_int32.funcs.decode = &read_varint;
     332           1 :         alltypes.sng_int32.arg = (void*)3041;
     333             :         
     334           1 :         alltypes.sng_int64.funcs.decode = &read_varint;
     335           1 :         alltypes.sng_int64.arg = (void*)3042;
     336             :         
     337           1 :         alltypes.sng_uint32.funcs.decode = &read_varint;
     338           1 :         alltypes.sng_uint32.arg = (void*)3043;
     339             :         
     340           1 :         alltypes.sng_uint64.funcs.decode = &read_varint;
     341           1 :         alltypes.sng_uint64.arg = (void*)3044;
     342             :         
     343           1 :         alltypes.sng_sint32.funcs.decode = &read_svarint;
     344           1 :         alltypes.sng_sint32.arg = (void*)3045;
     345             :         
     346           1 :         alltypes.sng_sint64.funcs.decode = &read_svarint;
     347           1 :         alltypes.sng_sint64.arg = (void*)3046;
     348             :         
     349           1 :         alltypes.sng_bool.funcs.decode = &read_varint;
     350           1 :         alltypes.sng_bool.arg = (void*)true;
     351             : 
     352           1 :         alltypes.sng_fixed32.funcs.decode = &read_fixed32;
     353           1 :         alltypes.sng_fixed32.arg = &sng_fixed32;
     354             :         
     355           1 :         alltypes.sng_sfixed32.funcs.decode = &read_fixed32;
     356           1 :         alltypes.sng_sfixed32.arg = &sng_sfixed32;
     357             :         
     358           1 :         alltypes.sng_float.funcs.decode = &read_fixed32;
     359           1 :         alltypes.sng_float.arg = &sng_float;
     360             :         
     361           1 :         alltypes.sng_fixed64.funcs.decode = &read_fixed64;
     362           1 :         alltypes.sng_fixed64.arg = &sng_fixed64;
     363             :         
     364           1 :         alltypes.sng_sfixed64.funcs.decode = &read_fixed64;
     365           1 :         alltypes.sng_sfixed64.arg = &sng_sfixed64;
     366             :         
     367           1 :         alltypes.sng_double.funcs.decode = &read_double;
     368           1 :         alltypes.sng_double.arg = &sng_double;
     369             :         
     370           1 :         alltypes.sng_string.funcs.decode = &read_string;
     371           1 :         alltypes.sng_string.arg = "3054";
     372             :         
     373           1 :         alltypes.sng_bytes.funcs.decode = &read_string;
     374           1 :         alltypes.sng_bytes.arg = "3055";
     375             :         
     376           1 :         alltypes.sng_submsg.funcs.decode = &read_submsg;
     377           1 :         alltypes.sng_submsg.arg = &sng_submsg;
     378             :         
     379           1 :         alltypes.sng_enum.funcs.decode = &read_varint;
     380           1 :         alltypes.sng_enum.arg = (void*)MyEnum_Truth;
     381             :         
     382           1 :         alltypes.sng_emptymsg.funcs.decode = &read_emptymsg;
     383             : 
     384           1 :         alltypes.oneof_msg1.funcs.decode = &read_submsg;
     385           1 :         alltypes.oneof_msg1.arg = &oneof_msg1;
     386             :     }
     387             :     
     388           2 :     status = pb_decode(stream, AllTypes_fields, &alltypes);
     389             :     
     390             : #ifdef PB_ENABLE_MALLOC
     391             :     /* Just to check for any interference between pb_release() and callback fields */
     392             :     pb_release(AllTypes_fields, &alltypes);
     393             : #endif
     394             : 
     395           2 :     return status;
     396             : }
     397             : 
     398           2 : int main(int argc, char **argv)
     399             : {
     400             :     uint8_t buffer[1024];
     401             :     size_t count;
     402             :     pb_istream_t stream;
     403             : 
     404             :     /* Whether to expect the optional values or the default values. */
     405           2 :     int mode = (argc > 1) ? atoi(argv[1]) : 0;
     406             :     
     407             :     /* Read the data into buffer */
     408             :     SET_BINARY_MODE(stdin);
     409           2 :     count = fread(buffer, 1, sizeof(buffer), stdin);
     410             :     
     411             :     /* Construct a pb_istream_t for reading from the buffer */
     412           2 :     stream = pb_istream_from_buffer(buffer, count);
     413             :     
     414             :     /* Decode and print out the stuff */
     415           2 :     if (!check_alltypes(&stream, mode))
     416             :     {
     417           0 :         printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
     418           0 :         return 1;
     419             :     } else {
     420           2 :         return 0;
     421             :     }
     422             : }

Generated by: LCOV version 1.14