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
read_callback(pb_istream_t * stream,uint8_t * buf,size_t count)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 }
write_callback(pb_ostream_t * stream,const uint8_t * buf,size_t count)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
main()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