LCOV - code coverage report
Current view: top level - encode_unittests - encode_unittests.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 213 216 98.6 %
Date: 2023-02-14 20:10:26 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* This includes the whole .c file to get access to static functions. */
       2             : #include "pb_common.c"
       3             : #include "pb_encode.c"
       4             : 
       5             : #include <stdio.h>
       6             : #include <string.h>
       7             : #include "unittests.h"
       8             : #include "unittestproto.pb.h"
       9             : 
      10           2 : bool streamcallback(pb_ostream_t *stream, const uint8_t *buf, size_t count)
      11             : {
      12             :     /* Allow only 'x' to be written */
      13           7 :     while (count--)
      14             :     {
      15           6 :         if (*buf++ != 'x')
      16           1 :             return false;
      17             :     }
      18           1 :     return true;
      19             : }
      20             : 
      21           6 : bool fieldcallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
      22             : {
      23           6 :     int value = 0x55;
      24           6 :     if (!pb_encode_tag_for_field(stream, field))
      25           0 :         return false;
      26           6 :     return pb_encode_varint(stream, value);
      27             : }
      28             : 
      29           2 : bool crazyfieldcallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
      30             : {
      31             :     /* This callback writes different amount of data the second time. */
      32           2 :     uint32_t *state = (uint32_t*)arg;
      33           2 :     *state <<= 8;
      34           2 :     if (!pb_encode_tag_for_field(stream, field))
      35           0 :         return false;
      36           2 :     return pb_encode_varint(stream, *state);
      37             : }
      38             : 
      39             : /* Check that expression x writes data y.
      40             :  * Y is a string, which may contain null bytes. Null terminator is ignored.
      41             :  */
      42             : #define WRITES(x, y) \
      43             : memset(buffer, 0xAA, sizeof(buffer)), \
      44             : s = pb_ostream_from_buffer(buffer, sizeof(buffer)), \
      45             : (x) && \
      46             : memcmp(buffer, y, sizeof(y) - 1) == 0 && \
      47             : buffer[sizeof(y) - 1] == 0xAA
      48             : 
      49           1 : int main()
      50             : {
      51           1 :     int status = 0;
      52             :     
      53             :     {
      54           1 :         uint8_t buffer1[] = "foobartest1234";
      55             :         uint8_t buffer2[sizeof(buffer1)];
      56           1 :         pb_ostream_t stream = pb_ostream_from_buffer(buffer2, sizeof(buffer1));
      57             :         
      58           1 :         COMMENT("Test pb_write and pb_ostream_t");
      59           1 :         TEST(pb_write(&stream, buffer1, sizeof(buffer1)));
      60           1 :         TEST(memcmp(buffer1, buffer2, sizeof(buffer1)) == 0);
      61           1 :         TEST(!pb_write(&stream, buffer1, 1));
      62           1 :         TEST(stream.bytes_written == sizeof(buffer1));
      63             :     }
      64             :     
      65             :     {
      66           1 :         uint8_t buffer1[] = "xxxxxxx";
      67           1 :         pb_ostream_t stream = {&streamcallback, 0, SIZE_MAX, 0};
      68             :         
      69           1 :         COMMENT("Test pb_write with custom callback");
      70           1 :         TEST(pb_write(&stream, buffer1, 5));
      71           1 :         buffer1[0] = 'a';
      72           1 :         TEST(!pb_write(&stream, buffer1, 5));
      73             :     }
      74             :     
      75             :     {
      76             :         uint8_t buffer[30];
      77             :         pb_ostream_t s;
      78             :         
      79           1 :         COMMENT("Test pb_encode_varint")
      80           1 :         TEST(WRITES(pb_encode_varint(&s, 0), "\0"));
      81           1 :         TEST(WRITES(pb_encode_varint(&s, 1), "\1"));
      82           1 :         TEST(WRITES(pb_encode_varint(&s, 0x7F), "\x7F"));
      83           1 :         TEST(WRITES(pb_encode_varint(&s, 0x80), "\x80\x01"));
      84           1 :         TEST(WRITES(pb_encode_varint(&s, UINT32_MAX), "\xFF\xFF\xFF\xFF\x0F"));
      85           1 :         TEST(WRITES(pb_encode_varint(&s, UINT64_MAX), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"));
      86             :     }
      87             :     
      88             :     {
      89             :         uint8_t buffer[50];
      90             :         pb_ostream_t s;
      91             :         
      92           1 :         COMMENT("Test pb_encode_varint 32-bit fast path")
      93           1 :         TEST(WRITES(pb_encode_varint(&s, 0x00000000), "\x00"));
      94           1 :         TEST(WRITES(pb_encode_varint(&s, 0x00000001), "\x01"));
      95           1 :         TEST(WRITES(pb_encode_varint(&s, 0x0000007F), "\x7F"));
      96           1 :         TEST(WRITES(pb_encode_varint(&s, 0x00000080), "\x80\x01"));
      97           1 :         TEST(WRITES(pb_encode_varint(&s, 0x00000191), "\x91\x03"));
      98           1 :         TEST(WRITES(pb_encode_varint(&s, 0x00003FFF), "\xFF\x7F"));
      99           1 :         TEST(WRITES(pb_encode_varint(&s, 0x00004000), "\x80\x80\x01"));
     100           1 :         TEST(WRITES(pb_encode_varint(&s, 0x0000D111), "\x91\xA2\x03"));
     101           1 :         TEST(WRITES(pb_encode_varint(&s, 0x001FFFFF), "\xFF\xFF\x7F"));
     102           1 :         TEST(WRITES(pb_encode_varint(&s, 0x00200000), "\x80\x80\x80\x01"));
     103           1 :         TEST(WRITES(pb_encode_varint(&s, 0x00711111), "\x91\xA2\xC4\x03"));
     104           1 :         TEST(WRITES(pb_encode_varint(&s, 0x0FFFFFFF), "\xFF\xFF\xFF\x7F"));
     105           1 :         TEST(WRITES(pb_encode_varint(&s, 0x10000000), "\x80\x80\x80\x80\x01"));
     106           1 :         TEST(WRITES(pb_encode_varint(&s, 0x31111111), "\x91\xA2\xC4\x88\x03"));
     107           1 :         TEST(WRITES(pb_encode_varint(&s, UINT32_MAX), "\xFF\xFF\xFF\xFF\x0F"));
     108             :     }
     109             :     
     110             :     {
     111             :         uint8_t buffer[50];
     112             :         pb_ostream_t s;
     113             :         
     114           1 :         COMMENT("Test pb_encode_svarint 32-bit fast path")
     115           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00000000), "\x00"));
     116           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xFFFFFFFF), "\x01"));
     117           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x0000003F), "\x7E"));
     118           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xFFFFFFC0), "\x7F"));
     119           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00000040), "\x80\x01"));
     120           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00001FFF), "\xFE\x7F"));
     121           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xFFFFE000), "\xFF\x7F"));
     122           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00002000), "\x80\x80\x01"));
     123           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x000FFFFF), "\xFE\xFF\x7F"));
     124           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xFFF00000), "\xFF\xFF\x7F"));
     125           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00100000), "\x80\x80\x80\x01"));
     126           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x07FFFFFF), "\xFE\xFF\xFF\x7F"));
     127           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xF8000000), "\xFF\xFF\xFF\x7F"));
     128           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x08000000), "\x80\x80\x80\x80\x01"));
     129           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x7FFFFFFF), "\xFE\xFF\xFF\xFF\x0F"));
     130           1 :         TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x80000000), "\xFF\xFF\xFF\xFF\x0F"));
     131             :     }
     132             :     
     133             :     {
     134             :         uint8_t buffer[30];
     135             :         pb_ostream_t s;
     136             :         
     137           1 :         COMMENT("Test pb_encode_tag")
     138           1 :         TEST(WRITES(pb_encode_tag(&s, PB_WT_STRING, 5), "\x2A"));
     139           1 :         TEST(WRITES(pb_encode_tag(&s, PB_WT_VARINT, 99), "\x98\x06"));
     140             :     }
     141             :     
     142             :     {
     143             :         uint8_t buffer[30];
     144             :         pb_ostream_t s;
     145             :         pb_field_iter_t field;
     146           1 :         field.tag = 10;
     147             : 
     148           1 :         COMMENT("Test pb_encode_tag_for_field")
     149           1 :         field.type = PB_LTYPE_SVARINT;
     150           1 :         TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x50"));
     151             :         
     152           1 :         field.type = PB_LTYPE_FIXED64;
     153           1 :         TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x51"));
     154             :         
     155           1 :         field.type = PB_LTYPE_STRING;
     156           1 :         TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x52"));
     157             :         
     158           1 :         field.type = PB_LTYPE_FIXED32;
     159           1 :         TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x55"));
     160             :     }
     161             :     
     162             :     {
     163             :         uint8_t buffer[30];
     164             :         pb_ostream_t s;
     165             :         
     166           1 :         COMMENT("Test pb_encode_string")
     167           1 :         TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"abcd", 4), "\x04""abcd"));
     168           1 :         TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"abcd\x00", 5), "\x05""abcd\x00"));
     169           1 :         TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"", 0), "\x00"));
     170             :     }
     171             :     
     172             :     {
     173             :         uint8_t buffer[30];
     174             :         pb_ostream_t s;
     175           1 :         uint8_t value = 1;
     176           1 :         int32_t max = INT32_MAX;
     177           1 :         int32_t min = INT32_MIN;
     178           1 :         int64_t lmax = INT64_MAX;
     179           1 :         int64_t lmin = INT64_MIN;
     180             :         pb_field_iter_t field;
     181             : 
     182           1 :         COMMENT("Test pb_enc_varint and pb_enc_svarint")
     183           1 :         field.type = PB_LTYPE_VARINT;
     184           1 :         field.data_size = sizeof(value);
     185           1 :         field.pData = &value;
     186           1 :         TEST(WRITES(pb_enc_varint(&s, &field), "\x01"));
     187             :         
     188           1 :         field.type = PB_LTYPE_SVARINT;
     189           1 :         field.data_size = sizeof(max);
     190           1 :         field.pData = &max;
     191           1 :         TEST(WRITES(pb_enc_varint(&s, &field), "\xfe\xff\xff\xff\x0f"));
     192             : 
     193           1 :         field.type = PB_LTYPE_SVARINT;
     194           1 :         field.data_size = sizeof(min);
     195           1 :         field.pData = &min;
     196           1 :         TEST(WRITES(pb_enc_varint(&s, &field), "\xff\xff\xff\xff\x0f"));
     197             :         
     198           1 :         field.type = PB_LTYPE_SVARINT;
     199           1 :         field.data_size = sizeof(lmax);
     200           1 :         field.pData = &lmax;
     201           1 :         TEST(WRITES(pb_enc_varint(&s, &field), "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"));
     202             : 
     203           1 :         field.type = PB_LTYPE_SVARINT;
     204           1 :         field.data_size = sizeof(lmin);
     205           1 :         field.pData = &lmin;
     206           1 :         TEST(WRITES(pb_enc_varint(&s, &field), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"));
     207             :     }
     208             :     
     209             :     {
     210             :         uint8_t buffer[30];
     211             :         pb_ostream_t s;
     212             :         float fvalue;
     213             :         double dvalue;
     214             :         pb_field_iter_t field;
     215             :         
     216           1 :         COMMENT("Test pb_enc_fixed using float")
     217           1 :         field.type = PB_LTYPE_FIXED32;
     218           1 :         field.data_size = sizeof(fvalue);
     219           1 :         field.pData = &fvalue;
     220           1 :         fvalue = 0.0f;
     221           1 :         TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\x00\x00"))
     222           1 :         fvalue = 99.0f;
     223           1 :         TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\xc6\x42"))
     224           1 :         fvalue = -12345678.0f;
     225           1 :         TEST(WRITES(pb_enc_fixed(&s, &field), "\x4e\x61\x3c\xcb"))
     226             :     
     227           1 :         COMMENT("Test pb_enc_fixed using double")
     228           1 :         field.type = PB_LTYPE_FIXED64;
     229           1 :         field.data_size = sizeof(dvalue);
     230           1 :         field.pData = &dvalue;
     231           1 :         dvalue = 0.0;
     232           1 :         TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\x00\x00\x00\x00\x00\x00"))
     233           1 :         dvalue = 99.0;
     234           1 :         TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\x00\x00\x00\xc0\x58\x40"))
     235           1 :         dvalue = -12345678.0;
     236           1 :         TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\x00\xc0\x29\x8c\x67\xc1"))
     237             :     }
     238             :     
     239             :     {
     240             :         uint8_t buffer[30];
     241             :         pb_ostream_t s;
     242           1 :         struct { pb_size_t size; uint8_t bytes[5]; } value = {5, {'x', 'y', 'z', 'z', 'y'}};
     243             :         pb_field_iter_t field;
     244           1 :         pb_field_iter_begin(&field, BytesMessage_fields, &value);
     245             : 
     246           1 :         COMMENT("Test pb_enc_bytes")
     247           1 :         TEST(WRITES(pb_enc_bytes(&s, &field), "\x05xyzzy"))
     248           1 :         value.size = 0;
     249           1 :         TEST(WRITES(pb_enc_bytes(&s, &field), "\x00"))
     250             :     }
     251             :     
     252             :     {
     253             :         uint8_t buffer[30];
     254             :         pb_ostream_t s;
     255           1 :         char value[30] = "xyzzy";
     256             :         pb_field_iter_t field;
     257           1 :         pb_field_iter_begin(&field, StringMessage_fields, &value);
     258             :         
     259           1 :         COMMENT("Test pb_enc_string")
     260           1 :         TEST(WRITES(pb_enc_string(&s, &field), "\x05xyzzy"))
     261           1 :         value[0] = '\0';
     262           1 :         TEST(WRITES(pb_enc_string(&s, &field), "\x00"))
     263           1 :         memset(value, 'x', 10);
     264           1 :         value[10] = '\0';
     265           1 :         TEST(WRITES(pb_enc_string(&s, &field), "\x0Axxxxxxxxxx"))
     266             :     }
     267             :     
     268             :     {
     269             :         uint8_t buffer[10];
     270             :         pb_ostream_t s;
     271           1 :         IntegerArray msg = {5, {1, 2, 3, 4, 5}};
     272             :         
     273           1 :         COMMENT("Test pb_encode with int32 array")
     274             :         
     275           1 :         TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), "\x0A\x05\x01\x02\x03\x04\x05"))
     276             :         
     277           1 :         msg.data_count = 0;
     278           1 :         TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), ""))
     279             :         
     280           1 :         msg.data_count = 10;
     281           1 :         TEST(!pb_encode(&s, IntegerArray_fields, &msg))
     282             :     }
     283             :     
     284             :     {
     285             :         uint8_t buffer[10];
     286             :         pb_ostream_t s;
     287           1 :         FloatArray msg = {1, {99.0f}};
     288             :         
     289           1 :         COMMENT("Test pb_encode with float array")
     290             :         
     291           1 :         TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg),
     292             :                     "\x0A\x04\x00\x00\xc6\x42"))
     293             :         
     294           1 :         msg.data_count = 0;
     295           1 :         TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg), ""))
     296             :         
     297           1 :         msg.data_count = 3;
     298           1 :         TEST(!pb_encode(&s, FloatArray_fields, &msg))
     299             :     }
     300             :     
     301             :     {
     302             :         uint8_t buffer[50];
     303             :         pb_ostream_t s;
     304           1 :         FloatArray msg = {1, {99.0f}};
     305             :         
     306           1 :         COMMENT("Test array size limit in pb_encode")
     307             :         
     308           1 :         s = pb_ostream_from_buffer(buffer, sizeof(buffer));
     309           1 :         TEST((msg.data_count = 10) && pb_encode(&s, FloatArray_fields, &msg))
     310             :         
     311           1 :         s = pb_ostream_from_buffer(buffer, sizeof(buffer));
     312           1 :         TEST((msg.data_count = 11) && !pb_encode(&s, FloatArray_fields, &msg))
     313             :     }
     314             :     
     315             :     {
     316             :         uint8_t buffer[10];
     317             :         pb_ostream_t s;
     318             :         CallbackArray msg;
     319             :         
     320           1 :         msg.data.funcs.encode = &fieldcallback;
     321             :         
     322           1 :         COMMENT("Test pb_encode with callback field.")
     323           1 :         TEST(WRITES(pb_encode(&s, CallbackArray_fields, &msg), "\x08\x55"))
     324             :     }
     325             :     
     326             :     {
     327             :         uint8_t buffer[10];
     328             :         pb_ostream_t s;
     329           1 :         IntegerContainer msg = {{5, {1,2,3,4,5}}};
     330             :         
     331           1 :         COMMENT("Test pb_encode with packed array in a submessage.")
     332           1 :         TEST(WRITES(pb_encode(&s, IntegerContainer_fields, &msg),
     333             :                     "\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"))
     334             :     }
     335             :     
     336             :     {
     337             :         uint8_t buffer[32];
     338             :         pb_ostream_t s;
     339           1 :         BytesMessage msg = {{3, "xyz"}};
     340             :         
     341           1 :         COMMENT("Test pb_encode with bytes message.")
     342           1 :         TEST(WRITES(pb_encode(&s, BytesMessage_fields, &msg),
     343             :                     "\x0A\x03xyz"))
     344             :         
     345           1 :         msg.data.size = 17; /* More than maximum */
     346           1 :         TEST(!pb_encode(&s, BytesMessage_fields, &msg))
     347             :     }
     348             :         
     349             :     
     350             :     {
     351             :         uint8_t buffer[20];
     352             :         pb_ostream_t s;
     353           1 :         IntegerContainer msg = {{5, {1,2,3,4,5}}};
     354             :         
     355           1 :         COMMENT("Test pb_encode_delimited.")
     356           1 :         TEST(WRITES(pb_encode_delimited(&s, IntegerContainer_fields, &msg),
     357             :                     "\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"))
     358             :     }
     359             : 
     360             :     {
     361           1 :         IntegerContainer msg = {{5, {1,2,3,4,5}}};
     362             :         size_t size;
     363             :         
     364           1 :         COMMENT("Test pb_get_encoded_size.")
     365           1 :         TEST(pb_get_encoded_size(&size, IntegerContainer_fields, &msg) &&
     366             :              size == 9);
     367             :     }
     368             :     
     369             :     {
     370             :         uint8_t buffer[10];
     371             :         pb_ostream_t s;
     372             :         CallbackContainer msg;
     373             :         CallbackContainerContainer msg2;
     374           1 :         uint32_t state = 1;
     375             :         
     376           1 :         msg.submsg.data.funcs.encode = &fieldcallback;
     377           1 :         msg2.submsg.submsg.data.funcs.encode = &fieldcallback;
     378             :         
     379           1 :         COMMENT("Test pb_encode with callback field in a submessage.")
     380           1 :         TEST(WRITES(pb_encode(&s, CallbackContainer_fields, &msg), "\x0A\x02\x08\x55"))
     381           1 :         TEST(WRITES(pb_encode(&s, CallbackContainerContainer_fields, &msg2),
     382             :                     "\x0A\x04\x0A\x02\x08\x55"))
     383             :         
     384             :         /* Misbehaving callback: varying output between calls */
     385           1 :         msg.submsg.data.funcs.encode = &crazyfieldcallback;
     386           1 :         msg.submsg.data.arg = &state;
     387           1 :         msg2.submsg.submsg.data.funcs.encode = &crazyfieldcallback;
     388           1 :         msg2.submsg.submsg.data.arg = &state;
     389             :         
     390           1 :         TEST(!pb_encode(&s, CallbackContainer_fields, &msg))
     391           1 :         state = 1;
     392           1 :         TEST(!pb_encode(&s, CallbackContainerContainer_fields, &msg2))
     393             :     }
     394             :     
     395             :     {
     396             :         uint8_t buffer[StringMessage_size];
     397             :         pb_ostream_t s;
     398           1 :         StringMessage msg = {"0123456789"};
     399             :         
     400           1 :         s = pb_ostream_from_buffer(buffer, sizeof(buffer));
     401             :         
     402           1 :         COMMENT("Test that StringMessage_size is correct")
     403             : 
     404           1 :         TEST(pb_encode(&s, StringMessage_fields, &msg));
     405           1 :         TEST(s.bytes_written == StringMessage_size);
     406             :     }
     407             :     
     408             :     {
     409             :         uint8_t buffer[128];
     410             :         pb_ostream_t s;
     411           1 :         StringPointerContainer msg = StringPointerContainer_init_zero;
     412           1 :         char *strs[1] = {NULL};
     413           1 :         char zstr[] = "Z";
     414             :         
     415           1 :         COMMENT("Test string pointer encoding.");
     416             :         
     417           1 :         msg.rep_str = strs;
     418           1 :         msg.rep_str_count = 1;
     419           1 :         TEST(WRITES(pb_encode(&s, StringPointerContainer_fields, &msg), "\x0a\x00"))
     420             :         
     421           1 :         strs[0] = zstr;
     422           1 :         TEST(WRITES(pb_encode(&s, StringPointerContainer_fields, &msg), "\x0a\x01Z"))
     423             :     }
     424             :     
     425           1 :     if (status != 0)
     426           0 :         fprintf(stdout, "\n\nSome tests FAILED!\n");
     427             :     
     428           1 :     return status;
     429             : }

Generated by: LCOV version 1.14