Line data Source code
1 : /* Attempts to test all the datatypes supported by ProtoBuf when used as callback fields.
2 : * Note that normally there would be no reason to use callback fields for this,
3 : * because each encoder defined here only gives a single field.
4 : */
5 :
6 : #include <stdio.h>
7 : #include <string.h>
8 : #include <stdlib.h>
9 : #include <pb_decode.h>
10 : #include "alltypes.pb.h"
11 : #include "test_helpers.h"
12 :
13 : #define TEST(x) if (!(x)) { \
14 : printf("Test %s failed (in field %d).\n", #x, field->tag); \
15 : return false; \
16 : }
17 :
18 8 : static bool read_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
19 : {
20 : uint64_t value;
21 8 : if (!pb_decode_varint(stream, &value))
22 0 : return false;
23 :
24 8 : TEST((int64_t)value == (intptr_t)*arg);
25 8 : return true;
26 : }
27 :
28 2 : static bool read_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
29 : {
30 : int64_t value;
31 2 : if (!pb_decode_svarint(stream, &value))
32 0 : return false;
33 :
34 2 : TEST(value == (intptr_t)*arg);
35 2 : return true;
36 : }
37 :
38 3 : static bool read_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
39 : {
40 : uint32_t value;
41 3 : if (!pb_decode_fixed32(stream, &value))
42 0 : return false;
43 :
44 3 : TEST(value == *(uint32_t*)*arg);
45 3 : return true;
46 : }
47 :
48 2 : static bool read_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
49 : {
50 : uint64_t value;
51 2 : if (!pb_decode_fixed64(stream, &value))
52 0 : return false;
53 :
54 2 : TEST(value == *(uint64_t*)*arg);
55 2 : return true;
56 : }
57 :
58 1 : static bool read_double(pb_istream_t *stream, const pb_field_t *field, void **arg)
59 : {
60 : #ifdef PB_CONVERT_DOUBLE_FLOAT
61 : if (sizeof(double) == sizeof(float))
62 : {
63 : float value;
64 : if (!pb_decode_double_as_float(stream, &value))
65 : return false;
66 :
67 : TEST(memcmp(&value, *arg, sizeof(float)) == 0);
68 : return true;
69 : }
70 : #endif
71 :
72 : uint64_t value;
73 1 : if (!pb_decode_fixed64(stream, &value))
74 0 : return false;
75 :
76 1 : TEST(value == *(uint64_t*)*arg);
77 1 : return true;
78 : }
79 :
80 2 : static bool read_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
81 : {
82 2 : uint8_t buf[16] = {0};
83 2 : size_t len = stream->bytes_left;
84 :
85 2 : if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
86 0 : return false;
87 :
88 2 : TEST(strcmp((char*)buf, *arg) == 0);
89 2 : return true;
90 : }
91 :
92 2 : static bool read_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
93 : {
94 2 : SubMessage submsg = {""};
95 2 : SubMessage *ref = *arg;
96 :
97 2 : if (!pb_decode(stream, SubMessage_fields, &submsg))
98 0 : return false;
99 :
100 2 : TEST(strcmp(submsg.substuff1, ref->substuff1) == 0);
101 2 : TEST(submsg.substuff2 == ref->substuff2);
102 2 : TEST(submsg.substuff3 == ref->substuff3);
103 2 : return true;
104 : }
105 :
106 11 : static bool read_emptymsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
107 : {
108 11 : EmptyMessage emptymsg = {0};
109 11 : return pb_decode(stream, EmptyMessage_fields, &emptymsg);
110 : }
111 :
112 60 : static bool read_repeated_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
113 : {
114 60 : int32_t** expected = (int32_t**)arg;
115 : uint64_t value;
116 60 : if (!pb_decode_varint(stream, &value))
117 0 : return false;
118 :
119 60 : TEST(*(*expected)++ == value);
120 60 : return true;
121 : }
122 :
123 20 : static bool read_repeated_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
124 : {
125 20 : int32_t** expected = (int32_t**)arg;
126 : int64_t value;
127 20 : if (!pb_decode_svarint(stream, &value))
128 0 : return false;
129 :
130 20 : TEST(*(*expected)++ == value);
131 20 : return true;
132 : }
133 :
134 30 : static bool read_repeated_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
135 : {
136 30 : uint32_t** expected = (uint32_t**)arg;
137 : uint32_t value;
138 30 : if (!pb_decode_fixed32(stream, &value))
139 0 : return false;
140 :
141 30 : TEST(*(*expected)++ == value);
142 30 : return true;
143 : }
144 :
145 20 : static bool read_repeated_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
146 : {
147 20 : uint64_t** expected = (uint64_t**)arg;
148 : uint64_t value;
149 20 : if (!pb_decode_fixed64(stream, &value))
150 0 : return false;
151 :
152 20 : TEST(*(*expected)++ == value);
153 20 : return true;
154 : }
155 :
156 10 : static bool read_repeated_double(pb_istream_t *stream, const pb_field_t *field, void **arg)
157 : {
158 : #ifdef PB_CONVERT_DOUBLE_FLOAT
159 : if (sizeof(double) == sizeof(float))
160 : {
161 : float** expectedf = (float**)arg;
162 : float value;
163 : if (!pb_decode_double_as_float(stream, &value))
164 : return false;
165 :
166 : TEST(memcmp(&value, (*expectedf)++, sizeof(float)) == 0);
167 : return true;
168 : }
169 : #endif
170 :
171 10 : uint64_t** expected = (uint64_t**)arg;
172 : uint64_t value;
173 10 : if (!pb_decode_fixed64(stream, &value))
174 0 : return false;
175 :
176 10 : TEST(*(*expected)++ == value);
177 10 : return true;
178 : }
179 :
180 20 : static bool read_repeated_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
181 : {
182 20 : uint8_t*** expected = (uint8_t***)arg;
183 20 : uint8_t buf[16] = {0};
184 20 : size_t len = stream->bytes_left;
185 :
186 20 : if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
187 0 : return false;
188 :
189 20 : TEST(strcmp((char*)*(*expected)++, (char*)buf) == 0);
190 20 : return true;
191 : }
192 :
193 10 : static bool read_repeated_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
194 : {
195 10 : SubMessage** expected = (SubMessage**)arg;
196 10 : SubMessage submsg = {""};
197 10 : if (!pb_decode(stream, SubMessage_fields, &submsg))
198 0 : return false;
199 :
200 10 : TEST(strcmp(submsg.substuff1, (*expected)->substuff1) == 0);
201 10 : TEST(submsg.substuff2 == (*expected)->substuff2);
202 10 : TEST(submsg.substuff3 == (*expected)->substuff3);
203 10 : (*expected)++;
204 :
205 10 : return true;
206 : }
207 :
208 2 : static bool read_limits(pb_istream_t *stream, const pb_field_t *field, void **arg)
209 : {
210 2 : Limits decoded = {0};
211 2 : if (!pb_decode(stream, Limits_fields, &decoded))
212 0 : return false;
213 :
214 2 : TEST(decoded.int32_min == INT32_MIN);
215 2 : TEST(decoded.int32_max == INT32_MAX);
216 2 : TEST(decoded.uint32_min == 0);
217 2 : TEST(decoded.uint32_max == UINT32_MAX);
218 2 : TEST(decoded.int64_min == INT64_MIN);
219 2 : TEST(decoded.int64_max == INT64_MAX);
220 2 : TEST(decoded.uint64_min == 0);
221 2 : TEST(decoded.uint64_max == UINT64_MAX);
222 2 : TEST(decoded.enum_min == HugeEnum_Negative);
223 2 : TEST(decoded.enum_max == HugeEnum_Positive);
224 :
225 2 : return true;
226 : }
227 :
228 : /* This function is called once from main(), it handles
229 : the decoding and checks the fields. */
230 2 : bool check_alltypes(pb_istream_t *stream, int mode)
231 : {
232 : /* Values for use from callbacks through pointers. */
233 : bool status;
234 :
235 2 : int32_t rep_int32[5] = {0, 0, 0, 0, -2001};
236 2 : int32_t rep_int64[5] = {0, 0, 0, 0, -2002};
237 2 : int32_t rep_uint32[5] = {0, 0, 0, 0, 2003};
238 2 : int32_t rep_uint64[5] = {0, 0, 0, 0, 2004};
239 2 : int32_t rep_sint32[5] = {0, 0, 0, 0, -2005};
240 2 : int32_t rep_sint64[5] = {0, 0, 0, 0, -2006};
241 2 : int32_t rep_bool[5] = {false, false, false, false, true};
242 2 : uint32_t rep_fixed32[5] = {0, 0, 0, 0, 2008};
243 2 : int32_t rep_sfixed32[5] = {0, 0, 0, 0, -2009};
244 2 : float rep_float[5] = {0, 0, 0, 0, 2010.0f};
245 2 : uint64_t rep_fixed64[5] = {0, 0, 0, 0, 2011};
246 2 : int64_t rep_sfixed64[5] = {0, 0, 0, 0, -2012};
247 2 : double rep_double[5] = {0, 0, 0, 0, 2013.0};
248 2 : char* rep_string[5] = {"", "", "", "", "2014"};
249 2 : char* rep_bytes[5] = {"", "", "", "", "2015"};
250 2 : SubMessage rep_submsg[5] = {{"", 0, 0},
251 : {"", 0, 0},
252 : {"", 0, 0},
253 : {"", 0, 0},
254 : {"2016", 2016, 2016}};
255 2 : int32_t rep_enum[5] = {0, 0, 0, 0, MyEnum_Truth};
256 :
257 2 : uint32_t sng_fixed32 = 3048;
258 2 : int32_t sng_sfixed32 = 3049;
259 2 : float sng_float = 3050.0f;
260 2 : uint64_t sng_fixed64 = 3051;
261 2 : int64_t sng_sfixed64 = 3052;
262 2 : double sng_double = 3053.0f;
263 2 : SubMessage sng_submsg = {"3056", 3056};
264 :
265 2 : SubMessage oneof_msg1 = {"4059", 4059};
266 :
267 2 : AllTypes alltypes = AllTypes_init_zero;
268 :
269 : /* Bind callbacks for repeated fields */
270 2 : alltypes.rep_int32.funcs.decode = &read_repeated_varint;
271 2 : alltypes.rep_int32.arg = rep_int32;
272 :
273 2 : alltypes.rep_int64.funcs.decode = &read_repeated_varint;
274 2 : alltypes.rep_int64.arg = rep_int64;
275 :
276 2 : alltypes.rep_uint32.funcs.decode = &read_repeated_varint;
277 2 : alltypes.rep_uint32.arg = rep_uint32;
278 :
279 2 : alltypes.rep_uint64.funcs.decode = &read_repeated_varint;
280 2 : alltypes.rep_uint64.arg = rep_uint64;
281 :
282 2 : alltypes.rep_sint32.funcs.decode = &read_repeated_svarint;
283 2 : alltypes.rep_sint32.arg = rep_sint32;
284 :
285 2 : alltypes.rep_sint64.funcs.decode = &read_repeated_svarint;
286 2 : alltypes.rep_sint64.arg = rep_sint64;
287 :
288 2 : alltypes.rep_bool.funcs.decode = &read_repeated_varint;
289 2 : alltypes.rep_bool.arg = rep_bool;
290 :
291 2 : alltypes.rep_fixed32.funcs.decode = &read_repeated_fixed32;
292 2 : alltypes.rep_fixed32.arg = rep_fixed32;
293 :
294 2 : alltypes.rep_sfixed32.funcs.decode = &read_repeated_fixed32;
295 2 : alltypes.rep_sfixed32.arg = rep_sfixed32;
296 :
297 2 : alltypes.rep_float.funcs.decode = &read_repeated_fixed32;
298 2 : alltypes.rep_float.arg = rep_float;
299 :
300 2 : alltypes.rep_fixed64.funcs.decode = &read_repeated_fixed64;
301 2 : alltypes.rep_fixed64.arg = rep_fixed64;
302 :
303 2 : alltypes.rep_sfixed64.funcs.decode = &read_repeated_fixed64;
304 2 : alltypes.rep_sfixed64.arg = rep_sfixed64;
305 :
306 2 : alltypes.rep_double.funcs.decode = &read_repeated_double;
307 2 : alltypes.rep_double.arg = rep_double;
308 :
309 2 : alltypes.rep_string.funcs.decode = &read_repeated_string;
310 2 : alltypes.rep_string.arg = rep_string;
311 :
312 2 : alltypes.rep_bytes.funcs.decode = &read_repeated_string;
313 2 : alltypes.rep_bytes.arg = rep_bytes;
314 :
315 2 : alltypes.rep_submsg.funcs.decode = &read_repeated_submsg;
316 2 : alltypes.rep_submsg.arg = rep_submsg;
317 :
318 2 : alltypes.rep_enum.funcs.decode = &read_repeated_varint;
319 2 : alltypes.rep_enum.arg = rep_enum;
320 :
321 2 : alltypes.rep_emptymsg.funcs.decode = &read_emptymsg;
322 :
323 2 : alltypes.req_limits.funcs.decode = &read_limits;
324 :
325 2 : alltypes.end.funcs.decode = &read_varint;
326 2 : alltypes.end.arg = (void*)1099;
327 :
328 : /* Bind callbacks for optional fields */
329 2 : if (mode == 1)
330 : {
331 1 : alltypes.sng_int32.funcs.decode = &read_varint;
332 1 : alltypes.sng_int32.arg = (void*)3041;
333 :
334 1 : alltypes.sng_int64.funcs.decode = &read_varint;
335 1 : alltypes.sng_int64.arg = (void*)3042;
336 :
337 1 : alltypes.sng_uint32.funcs.decode = &read_varint;
338 1 : alltypes.sng_uint32.arg = (void*)3043;
339 :
340 1 : alltypes.sng_uint64.funcs.decode = &read_varint;
341 1 : alltypes.sng_uint64.arg = (void*)3044;
342 :
343 1 : alltypes.sng_sint32.funcs.decode = &read_svarint;
344 1 : alltypes.sng_sint32.arg = (void*)3045;
345 :
346 1 : alltypes.sng_sint64.funcs.decode = &read_svarint;
347 1 : alltypes.sng_sint64.arg = (void*)3046;
348 :
349 1 : alltypes.sng_bool.funcs.decode = &read_varint;
350 1 : alltypes.sng_bool.arg = (void*)true;
351 :
352 1 : alltypes.sng_fixed32.funcs.decode = &read_fixed32;
353 1 : alltypes.sng_fixed32.arg = &sng_fixed32;
354 :
355 1 : alltypes.sng_sfixed32.funcs.decode = &read_fixed32;
356 1 : alltypes.sng_sfixed32.arg = &sng_sfixed32;
357 :
358 1 : alltypes.sng_float.funcs.decode = &read_fixed32;
359 1 : alltypes.sng_float.arg = &sng_float;
360 :
361 1 : alltypes.sng_fixed64.funcs.decode = &read_fixed64;
362 1 : alltypes.sng_fixed64.arg = &sng_fixed64;
363 :
364 1 : alltypes.sng_sfixed64.funcs.decode = &read_fixed64;
365 1 : alltypes.sng_sfixed64.arg = &sng_sfixed64;
366 :
367 1 : alltypes.sng_double.funcs.decode = &read_double;
368 1 : alltypes.sng_double.arg = &sng_double;
369 :
370 1 : alltypes.sng_string.funcs.decode = &read_string;
371 1 : alltypes.sng_string.arg = "3054";
372 :
373 1 : alltypes.sng_bytes.funcs.decode = &read_string;
374 1 : alltypes.sng_bytes.arg = "3055";
375 :
376 1 : alltypes.sng_submsg.funcs.decode = &read_submsg;
377 1 : alltypes.sng_submsg.arg = &sng_submsg;
378 :
379 1 : alltypes.sng_enum.funcs.decode = &read_varint;
380 1 : alltypes.sng_enum.arg = (void*)MyEnum_Truth;
381 :
382 1 : alltypes.sng_emptymsg.funcs.decode = &read_emptymsg;
383 :
384 1 : alltypes.oneof_msg1.funcs.decode = &read_submsg;
385 1 : alltypes.oneof_msg1.arg = &oneof_msg1;
386 : }
387 :
388 2 : status = pb_decode(stream, AllTypes_fields, &alltypes);
389 :
390 : #ifdef PB_ENABLE_MALLOC
391 : /* Just to check for any interference between pb_release() and callback fields */
392 : pb_release(AllTypes_fields, &alltypes);
393 : #endif
394 :
395 2 : return status;
396 : }
397 :
398 2 : int main(int argc, char **argv)
399 : {
400 : uint8_t buffer[1024];
401 : size_t count;
402 : pb_istream_t stream;
403 :
404 : /* Whether to expect the optional values or the default values. */
405 2 : int mode = (argc > 1) ? atoi(argv[1]) : 0;
406 :
407 : /* Read the data into buffer */
408 : SET_BINARY_MODE(stdin);
409 2 : count = fread(buffer, 1, sizeof(buffer), stdin);
410 :
411 : /* Construct a pb_istream_t for reading from the buffer */
412 2 : stream = pb_istream_from_buffer(buffer, count);
413 :
414 : /* Decode and print out the stuff */
415 2 : if (!check_alltypes(&stream, mode))
416 : {
417 0 : printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
418 0 : return 1;
419 : } else {
420 2 : return 0;
421 : }
422 : }
|