Home | History | Annotate | Download | only in io_errors
      1 /* Simulate IO errors after each byte in a stream.
      2  * Verifies proper error propagation.
      3  */
      4 
      5 #include <stdio.h>
      6 #include <pb_decode.h>
      7 #include <pb_encode.h>
      8 #include "alltypes.pb.h"
      9 #include "test_helpers.h"
     10 
     11 typedef struct
     12 {
     13     uint8_t *buffer;
     14     size_t fail_after;
     15 } faulty_stream_t;
     16 
     17 bool read_callback(pb_istream_t *stream, uint8_t *buf, size_t count)
     18 {
     19     faulty_stream_t *state = stream->state;
     20 
     21     while (count--)
     22     {
     23         if (state->fail_after == 0)
     24             PB_RETURN_ERROR(stream, "simulated");
     25         state->fail_after--;
     26         *buf++ = *state->buffer++;
     27     }
     28 
     29     return true;
     30 }
     31 bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count)
     32 {
     33     faulty_stream_t *state = stream->state;
     34 
     35     while (count--)
     36     {
     37         if (state->fail_after == 0)
     38             PB_RETURN_ERROR(stream, "simulated");
     39         state->fail_after--;
     40         *state->buffer++ = *buf++;
     41     }
     42 
     43     return true;
     44 }
     45 
     46 int main()
     47 {
     48     uint8_t buffer[2048];
     49     size_t msglen;
     50     AllTypes msg = AllTypes_init_zero;
     51 
     52     /* Get some base data to run the tests with */
     53     SET_BINARY_MODE(stdin);
     54     msglen = fread(buffer, 1, sizeof(buffer), stdin);
     55 
     56     /* Test IO errors on decoding */
     57     {
     58         bool status;
     59         pb_istream_t stream = {&read_callback, NULL, SIZE_MAX};
     60         faulty_stream_t fs;
     61         size_t i;
     62 
     63         for (i = 0; i < msglen; i++)
     64         {
     65             stream.bytes_left = msglen;
     66             stream.state = &fs;
     67             fs.buffer = buffer;
     68             fs.fail_after = i;
     69 
     70             status = pb_decode(&stream, AllTypes_fields, &msg);
     71             if (status != false)
     72             {
     73                 fprintf(stderr, "Unexpected success in decode\n");
     74                 return 2;
     75             }
     76             else if (strcmp(stream.errmsg, "simulated") != 0)
     77             {
     78                 fprintf(stderr, "Wrong error in decode: %s\n", stream.errmsg);
     79                 return 3;
     80             }
     81         }
     82 
     83         stream.bytes_left = msglen;
     84         stream.state = &fs;
     85         fs.buffer = buffer;
     86         fs.fail_after = msglen;
     87         status = pb_decode(&stream, AllTypes_fields, &msg);
     88 
     89         if (!status)
     90         {
     91             fprintf(stderr, "Decoding failed: %s\n", stream.errmsg);
     92             return 4;
     93         }
     94     }
     95 
     96     /* Test IO errors on encoding */
     97     {
     98         bool status;
     99         pb_ostream_t stream = {&write_callback, NULL, SIZE_MAX, 0};
    100         faulty_stream_t fs;
    101         size_t i;
    102 
    103         for (i = 0; i < msglen; i++)
    104         {
    105             stream.max_size = msglen;
    106             stream.bytes_written = 0;
    107             stream.state = &fs;
    108             fs.buffer = buffer;
    109             fs.fail_after = i;
    110 
    111             status = pb_encode(&stream, AllTypes_fields, &msg);
    112             if (status != false)
    113             {
    114                 fprintf(stderr, "Unexpected success in encode\n");
    115                 return 5;
    116             }
    117             else if (strcmp(stream.errmsg, "simulated") != 0)
    118             {
    119                 fprintf(stderr, "Wrong error in encode: %s\n", stream.errmsg);
    120                 return 6;
    121             }
    122         }
    123 
    124         stream.max_size = msglen;
    125         stream.bytes_written = 0;
    126         stream.state = &fs;
    127         fs.buffer = buffer;
    128         fs.fail_after = msglen;
    129         status = pb_encode(&stream, AllTypes_fields, &msg);
    130 
    131         if (!status)
    132         {
    133             fprintf(stderr, "Encoding failed: %s\n", stream.errmsg);
    134             return 7;
    135         }
    136     }
    137 
    138     return 0;
    139 }
    140 
    141