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