Home | History | Annotate | Download | only in alltypes_callback
      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 " #x " failed (in field %d).\n", field->tag); \
     15     return false; \
     16     }
     17 
     18 static bool read_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
     19 {
     20     uint64_t value;
     21     if (!pb_decode_varint(stream, &value))
     22         return false;
     23 
     24     TEST((int64_t)value == (long)*arg);
     25     return true;
     26 }
     27 
     28 static bool read_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
     29 {
     30     int64_t value;
     31     if (!pb_decode_svarint(stream, &value))
     32         return false;
     33 
     34     TEST(value == (long)*arg);
     35     return true;
     36 }
     37 
     38 static bool read_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
     39 {
     40     uint32_t value;
     41     if (!pb_decode_fixed32(stream, &value))
     42         return false;
     43 
     44     TEST(value == *(uint32_t*)*arg);
     45     return true;
     46 }
     47 
     48 static bool read_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
     49 {
     50     uint64_t value;
     51     if (!pb_decode_fixed64(stream, &value))
     52         return false;
     53 
     54     TEST(value == *(uint64_t*)*arg);
     55     return true;
     56 }
     57 
     58 static bool read_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
     59 {
     60     uint8_t buf[16] = {0};
     61     size_t len = stream->bytes_left;
     62 
     63     if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
     64         return false;
     65 
     66     TEST(strcmp((char*)buf, *arg) == 0);
     67     return true;
     68 }
     69 
     70 static bool read_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
     71 {
     72     SubMessage submsg = {""};
     73 
     74     if (!pb_decode(stream, SubMessage_fields, &submsg))
     75         return false;
     76 
     77     TEST(memcmp(&submsg, *arg, sizeof(submsg)));
     78     return true;
     79 }
     80 
     81 static bool read_emptymsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
     82 {
     83     EmptyMessage emptymsg = {0};
     84     return pb_decode(stream, EmptyMessage_fields, &emptymsg);
     85 }
     86 
     87 static bool read_repeated_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
     88 {
     89     int32_t** expected = (int32_t**)arg;
     90     uint64_t value;
     91     if (!pb_decode_varint(stream, &value))
     92         return false;
     93 
     94     TEST(*(*expected)++ == value);
     95     return true;
     96 }
     97 
     98 static bool read_repeated_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
     99 {
    100     int32_t** expected = (int32_t**)arg;
    101     int64_t value;
    102     if (!pb_decode_svarint(stream, &value))
    103         return false;
    104 
    105     TEST(*(*expected)++ == value);
    106     return true;
    107 }
    108 
    109 static bool read_repeated_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
    110 {
    111     uint32_t** expected = (uint32_t**)arg;
    112     uint32_t value;
    113     if (!pb_decode_fixed32(stream, &value))
    114         return false;
    115 
    116     TEST(*(*expected)++ == value);
    117     return true;
    118 }
    119 
    120 static bool read_repeated_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
    121 {
    122     uint64_t** expected = (uint64_t**)arg;
    123     uint64_t value;
    124     if (!pb_decode_fixed64(stream, &value))
    125         return false;
    126 
    127     TEST(*(*expected)++ == value);
    128     return true;
    129 }
    130 
    131 static bool read_repeated_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
    132 {
    133     uint8_t*** expected = (uint8_t***)arg;
    134     uint8_t buf[16] = {0};
    135     size_t len = stream->bytes_left;
    136 
    137     if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
    138         return false;
    139 
    140     TEST(strcmp((char*)*(*expected)++, (char*)buf) == 0);
    141     return true;
    142 }
    143 
    144 static bool read_repeated_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
    145 {
    146     SubMessage** expected = (SubMessage**)arg;
    147     SubMessage decoded = {""};
    148     if (!pb_decode(stream, SubMessage_fields, &decoded))
    149         return false;
    150 
    151     TEST(memcmp((*expected)++, &decoded, sizeof(decoded)) == 0);
    152     return true;
    153 }
    154 
    155 static bool read_limits(pb_istream_t *stream, const pb_field_t *field, void **arg)
    156 {
    157     Limits decoded = {0};
    158     if (!pb_decode(stream, Limits_fields, &decoded))
    159         return false;
    160 
    161     TEST(decoded.int32_min  == INT32_MIN);
    162     TEST(decoded.int32_max  == INT32_MAX);
    163     TEST(decoded.uint32_min == 0);
    164     TEST(decoded.uint32_max == UINT32_MAX);
    165     TEST(decoded.int64_min  == INT64_MIN);
    166     TEST(decoded.int64_max  == INT64_MAX);
    167     TEST(decoded.uint64_min == 0);
    168     TEST(decoded.uint64_max == UINT64_MAX);
    169     TEST(decoded.enum_min   == HugeEnum_Negative);
    170     TEST(decoded.enum_max   == HugeEnum_Positive);
    171 
    172     return true;
    173 }
    174 
    175 /* This function is called once from main(), it handles
    176    the decoding and checks the fields. */
    177 bool check_alltypes(pb_istream_t *stream, int mode)
    178 {
    179     /* Values for use from callbacks through pointers. */
    180     uint32_t    req_fixed32     = 1008;
    181     int32_t     req_sfixed32    = -1009;
    182     float       req_float       = 1010.0f;
    183     uint64_t    req_fixed64     = 1011;
    184     int64_t     req_sfixed64    = -1012;
    185     double      req_double      = 1013.0;
    186     SubMessage  req_submsg      = {"1016", 1016};
    187 
    188     int32_t     rep_int32[5]    = {0, 0, 0, 0, -2001};
    189     int32_t     rep_int64[5]    = {0, 0, 0, 0, -2002};
    190     int32_t     rep_uint32[5]   = {0, 0, 0, 0,  2003};
    191     int32_t     rep_uint64[5]   = {0, 0, 0, 0,  2004};
    192     int32_t     rep_sint32[5]   = {0, 0, 0, 0, -2005};
    193     int32_t     rep_sint64[5]   = {0, 0, 0, 0, -2006};
    194     int32_t     rep_bool[5]     = {false, false, false, false, true};
    195     uint32_t    rep_fixed32[5]  = {0, 0, 0, 0,  2008};
    196     int32_t     rep_sfixed32[5] = {0, 0, 0, 0, -2009};
    197     float       rep_float[5]    = {0, 0, 0, 0,  2010.0f};
    198     uint64_t    rep_fixed64[5]  = {0, 0, 0, 0,  2011};
    199     int64_t     rep_sfixed64[5] = {0, 0, 0, 0, -2012};
    200     double      rep_double[5]   = {0, 0, 0, 0,  2013.0};
    201     char*       rep_string[5]   = {"", "", "", "", "2014"};
    202     char*       rep_bytes[5]    = {"", "", "", "", "2015"};
    203     SubMessage  rep_submsg[5]   = {{"", 0, 0, 3},
    204                                    {"", 0, 0, 3},
    205                                    {"", 0, 0, 3},
    206                                    {"", 0, 0, 3},
    207                                    {"2016", 2016, true, 2016}};
    208     int32_t     rep_enum[5]     = {0, 0, 0, 0, MyEnum_Truth};
    209 
    210     uint32_t    opt_fixed32     = 3048;
    211     int32_t     opt_sfixed32    = 3049;
    212     float       opt_float       = 3050.0f;
    213     uint64_t    opt_fixed64     = 3051;
    214     int64_t     opt_sfixed64    = 3052;
    215     double      opt_double      = 3053.0f;
    216     SubMessage  opt_submsg      = {"3056", 3056};
    217 
    218     /* Bind callbacks for required fields */
    219     AllTypes alltypes;
    220 
    221     /* Fill with garbage to better detect initialization errors */
    222     memset(&alltypes, 0xAA, sizeof(alltypes));
    223 
    224     alltypes.req_int32.funcs.decode = &read_varint;
    225     alltypes.req_int32.arg = (void*)-1001;
    226 
    227     alltypes.req_int64.funcs.decode = &read_varint;
    228     alltypes.req_int64.arg = (void*)-1002;
    229 
    230     alltypes.req_uint32.funcs.decode = &read_varint;
    231     alltypes.req_uint32.arg = (void*)1003;
    232 
    233     alltypes.req_uint32.funcs.decode = &read_varint;
    234     alltypes.req_uint32.arg = (void*)1003;
    235 
    236     alltypes.req_uint64.funcs.decode = &read_varint;
    237     alltypes.req_uint64.arg = (void*)1004;
    238 
    239     alltypes.req_sint32.funcs.decode = &read_svarint;
    240     alltypes.req_sint32.arg = (void*)-1005;
    241 
    242     alltypes.req_sint64.funcs.decode = &read_svarint;
    243     alltypes.req_sint64.arg = (void*)-1006;
    244 
    245     alltypes.req_bool.funcs.decode = &read_varint;
    246     alltypes.req_bool.arg = (void*)true;
    247 
    248     alltypes.req_fixed32.funcs.decode = &read_fixed32;
    249     alltypes.req_fixed32.arg = &req_fixed32;
    250 
    251     alltypes.req_sfixed32.funcs.decode = &read_fixed32;
    252     alltypes.req_sfixed32.arg = &req_sfixed32;
    253 
    254     alltypes.req_float.funcs.decode = &read_fixed32;
    255     alltypes.req_float.arg = &req_float;
    256 
    257     alltypes.req_fixed64.funcs.decode = &read_fixed64;
    258     alltypes.req_fixed64.arg = &req_fixed64;
    259 
    260     alltypes.req_sfixed64.funcs.decode = &read_fixed64;
    261     alltypes.req_sfixed64.arg = &req_sfixed64;
    262 
    263     alltypes.req_double.funcs.decode = &read_fixed64;
    264     alltypes.req_double.arg = &req_double;
    265 
    266     alltypes.req_string.funcs.decode = &read_string;
    267     alltypes.req_string.arg = "1014";
    268 
    269     alltypes.req_bytes.funcs.decode = &read_string;
    270     alltypes.req_bytes.arg = "1015";
    271 
    272     alltypes.req_submsg.funcs.decode = &read_submsg;
    273     alltypes.req_submsg.arg = &req_submsg;
    274 
    275     alltypes.req_enum.funcs.decode = &read_varint;
    276     alltypes.req_enum.arg = (void*)MyEnum_Truth;
    277 
    278     alltypes.req_emptymsg.funcs.decode = &read_emptymsg;
    279 
    280     /* Bind callbacks for repeated fields */
    281     alltypes.rep_int32.funcs.decode = &read_repeated_varint;
    282     alltypes.rep_int32.arg = rep_int32;
    283 
    284     alltypes.rep_int64.funcs.decode = &read_repeated_varint;
    285     alltypes.rep_int64.arg = rep_int64;
    286 
    287     alltypes.rep_uint32.funcs.decode = &read_repeated_varint;
    288     alltypes.rep_uint32.arg = rep_uint32;
    289 
    290     alltypes.rep_uint64.funcs.decode = &read_repeated_varint;
    291     alltypes.rep_uint64.arg = rep_uint64;
    292 
    293     alltypes.rep_sint32.funcs.decode = &read_repeated_svarint;
    294     alltypes.rep_sint32.arg = rep_sint32;
    295 
    296     alltypes.rep_sint64.funcs.decode = &read_repeated_svarint;
    297     alltypes.rep_sint64.arg = rep_sint64;
    298 
    299     alltypes.rep_bool.funcs.decode = &read_repeated_varint;
    300     alltypes.rep_bool.arg = rep_bool;
    301 
    302     alltypes.rep_fixed32.funcs.decode = &read_repeated_fixed32;
    303     alltypes.rep_fixed32.arg = rep_fixed32;
    304 
    305     alltypes.rep_sfixed32.funcs.decode = &read_repeated_fixed32;
    306     alltypes.rep_sfixed32.arg = rep_sfixed32;
    307 
    308     alltypes.rep_float.funcs.decode = &read_repeated_fixed32;
    309     alltypes.rep_float.arg = rep_float;
    310 
    311     alltypes.rep_fixed64.funcs.decode = &read_repeated_fixed64;
    312     alltypes.rep_fixed64.arg = rep_fixed64;
    313 
    314     alltypes.rep_sfixed64.funcs.decode = &read_repeated_fixed64;
    315     alltypes.rep_sfixed64.arg = rep_sfixed64;
    316 
    317     alltypes.rep_double.funcs.decode = &read_repeated_fixed64;
    318     alltypes.rep_double.arg = rep_double;
    319 
    320     alltypes.rep_string.funcs.decode = &read_repeated_string;
    321     alltypes.rep_string.arg = rep_string;
    322 
    323     alltypes.rep_bytes.funcs.decode = &read_repeated_string;
    324     alltypes.rep_bytes.arg = rep_bytes;
    325 
    326     alltypes.rep_submsg.funcs.decode = &read_repeated_submsg;
    327     alltypes.rep_submsg.arg = rep_submsg;
    328 
    329     alltypes.rep_enum.funcs.decode = &read_repeated_varint;
    330     alltypes.rep_enum.arg = rep_enum;
    331 
    332     alltypes.rep_emptymsg.funcs.decode = &read_emptymsg;
    333 
    334     alltypes.req_limits.funcs.decode = &read_limits;
    335 
    336     alltypes.end.funcs.decode = &read_varint;
    337     alltypes.end.arg = (void*)1099;
    338 
    339     /* Bind callbacks for optional fields */
    340     if (mode == 1)
    341     {
    342         alltypes.opt_int32.funcs.decode = &read_varint;
    343         alltypes.opt_int32.arg = (void*)3041;
    344 
    345         alltypes.opt_int64.funcs.decode = &read_varint;
    346         alltypes.opt_int64.arg = (void*)3042;
    347 
    348         alltypes.opt_uint32.funcs.decode = &read_varint;
    349         alltypes.opt_uint32.arg = (void*)3043;
    350 
    351         alltypes.opt_uint64.funcs.decode = &read_varint;
    352         alltypes.opt_uint64.arg = (void*)3044;
    353 
    354         alltypes.opt_sint32.funcs.decode = &read_svarint;
    355         alltypes.opt_sint32.arg = (void*)3045;
    356 
    357         alltypes.opt_sint64.funcs.decode = &read_svarint;
    358         alltypes.opt_sint64.arg = (void*)3046;
    359 
    360         alltypes.opt_bool.funcs.decode = &read_varint;
    361         alltypes.opt_bool.arg = (void*)true;
    362 
    363         alltypes.opt_fixed32.funcs.decode = &read_fixed32;
    364         alltypes.opt_fixed32.arg = &opt_fixed32;
    365 
    366         alltypes.opt_sfixed32.funcs.decode = &read_fixed32;
    367         alltypes.opt_sfixed32.arg = &opt_sfixed32;
    368 
    369         alltypes.opt_float.funcs.decode = &read_fixed32;
    370         alltypes.opt_float.arg = &opt_float;
    371 
    372         alltypes.opt_fixed64.funcs.decode = &read_fixed64;
    373         alltypes.opt_fixed64.arg = &opt_fixed64;
    374 
    375         alltypes.opt_sfixed64.funcs.decode = &read_fixed64;
    376         alltypes.opt_sfixed64.arg = &opt_sfixed64;
    377 
    378         alltypes.opt_double.funcs.decode = &read_fixed64;
    379         alltypes.opt_double.arg = &opt_double;
    380 
    381         alltypes.opt_string.funcs.decode = &read_string;
    382         alltypes.opt_string.arg = "3054";
    383 
    384         alltypes.opt_bytes.funcs.decode = &read_string;
    385         alltypes.opt_bytes.arg = "3055";
    386 
    387         alltypes.opt_submsg.funcs.decode = &read_submsg;
    388         alltypes.opt_submsg.arg = &opt_submsg;
    389 
    390         alltypes.opt_enum.funcs.decode = &read_varint;
    391         alltypes.opt_enum.arg = (void*)MyEnum_Truth;
    392 
    393         alltypes.opt_emptymsg.funcs.decode = &read_emptymsg;
    394     }
    395 
    396     return pb_decode(stream, AllTypes_fields, &alltypes);
    397 }
    398 
    399 int main(int argc, char **argv)
    400 {
    401     uint8_t buffer[1024];
    402     size_t count;
    403     pb_istream_t stream;
    404 
    405     /* Whether to expect the optional values or the default values. */
    406     int mode = (argc > 1) ? atoi(argv[1]) : 0;
    407 
    408     /* Read the data into buffer */
    409     SET_BINARY_MODE(stdin);
    410     count = fread(buffer, 1, sizeof(buffer), stdin);
    411 
    412     /* Construct a pb_istream_t for reading from the buffer */
    413     stream = pb_istream_from_buffer(buffer, count);
    414 
    415     /* Decode and print out the stuff */
    416     if (!check_alltypes(&stream, mode))
    417     {
    418         printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
    419         return 1;
    420     } else {
    421         return 0;
    422     }
    423 }
    424