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