1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to you under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  * https://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14  * implied.  See the License for the specific language governing
15  * permissions and limitations under the License.
16  */
17 
18 /* Test cases for the new avro_value_t interface */
19 
20 #include <limits.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24 
25 #include "avro.h"
26 #include "avro_private.h"
27 
28 typedef int (*avro_test) (void);
29 
30 #ifndef SHOW_ALLOCATIONS
31 #define SHOW_ALLOCATIONS 0
32 #endif
33 
34 /*
35  * Use a custom allocator that verifies that the size that we use to
36  * free an object matches the size that we use to allocate it.
37  */
38 
39 static void *
test_allocator(void * ud,void * ptr,size_t osize,size_t nsize)40 test_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
41 {
42 	AVRO_UNUSED(ud);
43 	AVRO_UNUSED(osize);
44 
45 #if SHOW_ALLOCATIONS
46 	fprintf(stderr, "alloc(%p, %" PRIsz ", %" PRIsz ") => ", ptr, osize, nsize);
47 #endif
48 
49 	if (nsize == 0) {
50 		size_t  *size = ((size_t *) ptr) - 1;
51 		if (osize != *size) {
52 			fprintf(stderr,
53 #if SHOW_ALLOCATIONS
54 				"ERROR!\n"
55 #endif
56 				"Error freeing %p:\n"
57 				"Size passed to avro_free (%" PRIsz ") "
58 				"doesn't match size passed to "
59 				"avro_malloc (%" PRIsz ")\n",
60 				ptr, osize, *size);
61 			exit(EXIT_FAILURE);
62 		}
63 		free(size);
64 #if SHOW_ALLOCATIONS
65 		fprintf(stderr, "NULL\n");
66 #endif
67 		return NULL;
68 	} else {
69 		size_t  real_size = nsize + sizeof(size_t);
70 		size_t  *old_size = ptr? ((size_t *) ptr)-1: NULL;
71 		size_t  *size = (size_t *) realloc(old_size, real_size);
72 		*size = nsize;
73 #if SHOW_ALLOCATIONS
74 		fprintf(stderr, "%p\n", (size+1));
75 #endif
76 		return (size + 1);
77 	}
78 }
79 
80 void
init_rand(void)81 init_rand(void)
82 {
83 	srand(time(NULL));
84 }
85 
86 double
rand_number(double from,double to)87 rand_number(double from, double to)
88 {
89 	double range = to - from;
90 	return from + ((double)rand() / (RAND_MAX + 1.0)) * range;
91 }
92 
93 int64_t
rand_int64(void)94 rand_int64(void)
95 {
96 	return (int64_t) rand_number(LONG_MIN, LONG_MAX);
97 }
98 
99 int32_t
rand_int32(void)100 rand_int32(void)
101 {
102 	return (int32_t) rand_number(INT_MIN, INT_MAX);
103 }
104 
105 size_t
rand_count(void)106 rand_count(void)
107 {
108 	return (size_t) rand_number(0, 100);
109 }
110 
111 #define check_(call) \
112 	do { \
113 		int _rval = call; \
114 		if (_rval) { return _rval; } \
115 	} while (0)
116 
117 /*
118  * Verify that we can't call any of the getters and setters that don't
119  * apply to the given value.
120  */
121 
122 static int
_check_invalid_methods(const char * name,avro_value_t * val)123 _check_invalid_methods(const char *name, avro_value_t *val)
124 {
125 	avro_type_t  type = avro_value_get_type(val);
126 
127 /* For a description on GCC vs Visual Studio 2008 usage of variadic
128  * macros see:
129  * https://stackoverflow.com/questions/2575864/the-problem-about-different
130  * -treatment-to-va-args-when-using-vs-2008-and-gcc
131  */
132 #define expand_args(...) __VA_ARGS__
133 #define check_bad(method, ...) \
134 	do { \
135           if (!expand_args(avro_value_##method(__VA_ARGS__))) {  \
136 			fprintf(stderr, \
137 				"Shouldn't be able to " #method " a %s\n", \
138 				name); \
139 			return EXIT_FAILURE; \
140 		} \
141 	} while (0)
142 
143 	if (type != AVRO_BOOLEAN) {
144 		int  dummy = 0;
145 		check_bad(get_boolean, val, &dummy);
146 		check_bad(set_boolean, val, dummy);
147 	}
148 
149 	if (type != AVRO_BYTES) {
150 		const void  *cbuf = NULL;
151 		void  *buf = NULL;
152 		size_t  size = 0;
153 		check_bad(get_bytes, val, &cbuf, &size);
154 		check_bad(set_bytes, val, buf, size);
155 	}
156 
157 	if (type != AVRO_DOUBLE) {
158 		double  dummy = 0;
159 		check_bad(get_double, val, &dummy);
160 		check_bad(set_double, val, dummy);
161 	}
162 
163 	if (type != AVRO_FLOAT) {
164 		float  dummy = 0;
165 		check_bad(get_float, val, &dummy);
166 		check_bad(set_float, val, dummy);
167 	}
168 
169 	if (type != AVRO_INT32) {
170 		int32_t  dummy = 0;
171 		check_bad(get_int, val, &dummy);
172 		check_bad(set_int, val, dummy);
173 	}
174 
175 	if (type != AVRO_INT64) {
176 		int64_t  dummy = 0;
177 		check_bad(get_long, val, &dummy);
178 		check_bad(set_long, val, dummy);
179 	}
180 
181 	if (type != AVRO_NULL) {
182 		check_bad(get_null, val);
183 		check_bad(set_null, val);
184 	}
185 
186 	if (type != AVRO_STRING) {
187 		const char  *cstr = NULL;
188 		char  *str = NULL;
189 		size_t  size = 0;
190 		check_bad(get_string, val, &cstr, &size);
191 		check_bad(set_string, val, str);
192 		check_bad(set_string_len, val, str, size);
193 	}
194 
195 	if (type != AVRO_ENUM) {
196 		int  dummy = 0;
197 		check_bad(get_enum, val, &dummy);
198 		check_bad(set_enum, val, dummy);
199 	}
200 
201 	if (type != AVRO_FIXED) {
202 		const void  *cbuf = NULL;
203 		void  *buf = NULL;
204 		size_t  size = 0;
205 		check_bad(get_fixed, val, &cbuf, &size);
206 		check_bad(set_fixed, val, buf, size);
207 	}
208 
209 	if (type != AVRO_ARRAY && type != AVRO_MAP && type != AVRO_RECORD) {
210 		size_t  size = 0;
211 		check_bad(get_size, val, &size);
212 
213 		size_t  index = 0;
214 		avro_value_t  child;
215 		const char  *key = NULL;
216 		check_bad(get_by_index, val, index, &child, &key);
217 	}
218 
219 	if (type != AVRO_MAP && type != AVRO_RECORD) {
220 		const char  *key = NULL;
221 		avro_value_t  child;
222 		size_t  index = 0;
223 		check_bad(get_by_name, val, key, &child, &index);
224 	}
225 
226 	if (type != AVRO_ARRAY) {
227 		avro_value_t  child;
228 		size_t  index;
229 		check_bad(append, val, &child, &index);
230 	}
231 
232 	if (type != AVRO_MAP) {
233 		const char  *key = NULL;
234 		avro_value_t  child;
235 		size_t  index = 0;
236 		int  is_new = 0;
237 		check_bad(add, val, key, &child, &index, &is_new);
238 	}
239 
240 	if (type != AVRO_UNION) {
241 		int  discriminant = 0;
242 		avro_value_t  branch;
243 		check_bad(get_discriminant, val, &discriminant);
244 		check_bad(get_current_branch, val, &branch);
245 		check_bad(set_branch, val, discriminant, &branch);
246 	}
247 
248 #undef check_bad
249 
250 	return EXIT_SUCCESS;
251 }
252 
253 #define check_invalid_methods(name, val) \
254 	check_(_check_invalid_methods(name, val))
255 
256 /*
257  * Verify that we get the expected type code and schema for a value.
258  */
259 
260 static int
check_type_and_schema(const char * name,avro_value_t * val,avro_type_t expected_type,avro_schema_t expected_schema)261 check_type_and_schema(const char *name,
262 		      avro_value_t *val,
263 		      avro_type_t expected_type,
264 		      avro_schema_t expected_schema)
265 {
266 	if (avro_value_get_type(val) != expected_type) {
267 		avro_schema_decref(expected_schema);
268 		fprintf(stderr, "Unexpected type for %s\n", name);
269 		return EXIT_FAILURE;
270 	}
271 
272 	if (!avro_schema_equal(avro_value_get_schema(val),
273 			       expected_schema)) {
274 		avro_schema_decref(expected_schema);
275 		fprintf(stderr, "Unexpected schema for %s\n", name);
276 		return EXIT_FAILURE;
277 	}
278 
279 	avro_schema_decref(expected_schema);
280 	return EXIT_SUCCESS;
281 }
282 
283 #define try(call, msg) \
284 	do { \
285 		if (call) { \
286 			fprintf(stderr, msg ":\n  %s\n", avro_strerror()); \
287 			return EXIT_FAILURE; \
288 		} \
289 	} while (0)
290 
291 static int
_check_write_read(avro_value_t * val)292 _check_write_read(avro_value_t *val)
293 {
294 	static char  buf[4096];
295 
296 	avro_reader_t  reader = avro_reader_memory(buf, sizeof(buf));
297 	avro_writer_t  writer = avro_writer_memory(buf, sizeof(buf));
298 
299 	if (avro_value_write(writer, val)) {
300 		fprintf(stderr, "Unable to write value:\n  %s\n",
301 			avro_strerror());
302 		return EXIT_FAILURE;
303 	}
304 
305 	avro_writer_dump(writer, stderr);
306 
307 	size_t size;
308 	if (avro_value_sizeof(val, &size)) {
309 		fprintf(stderr, "Unable to determine size of value:\n  %s\n",
310 			avro_strerror());
311 		return EXIT_FAILURE;
312 	}
313 
314 	if (size != (size_t) avro_writer_tell(writer)) {
315 		fprintf(stderr, "Unexpected size of encoded value\n");
316 		return EXIT_FAILURE;
317 	}
318 
319 	avro_value_t  val_in;
320 	if (avro_generic_value_new(val->iface, &val_in)) {
321 		fprintf(stderr, "Cannot allocate new value instance:\n  %s\n",
322 			avro_strerror());
323 		return EXIT_FAILURE;
324 	}
325 
326 	if (avro_value_read(reader, &val_in)) {
327 		fprintf(stderr, "Unable to read value:\n  %s\n",
328 			avro_strerror());
329 		return EXIT_FAILURE;
330 	}
331 
332 	if (!avro_value_equal(val, &val_in)) {
333 		fprintf(stderr, "Round-trip values not equal\n");
334 		exit(EXIT_FAILURE);
335 	}
336 
337 	avro_value_decref(&val_in);
338 	avro_reader_free(reader);
339 	avro_writer_free(writer);
340 
341 	return EXIT_SUCCESS;
342 }
343 
344 #define check_write_read(val) \
345 	check_(_check_write_read(val))
346 
347 static int
_check_hash(avro_value_t * val1,avro_value_t * val2)348 _check_hash(avro_value_t *val1, avro_value_t *val2)
349 {
350 	uint32_t  hash1 = avro_value_hash(val1);
351 	uint32_t  hash2 = avro_value_hash(val2);
352 	if (hash1 != hash2) {
353 		fprintf(stderr, "Copied hashed not equal\n");
354 		return EXIT_FAILURE;
355 	}
356 	return EXIT_SUCCESS;
357 }
358 
359 #define check_hash(val1, val2) \
360 	check_(_check_hash(val1, val2))
361 
362 static int
_check_copy(avro_value_t * val)363 _check_copy(avro_value_t *val)
364 {
365 	avro_value_t  copied_val;
366 	if (avro_generic_value_new(val->iface, &copied_val)) {
367 		fprintf(stderr, "Cannot allocate new value instance:\n  %s\n",
368 			avro_strerror());
369 		return EXIT_FAILURE;
370 	}
371 
372 	if (avro_value_copy_fast(&copied_val, val)) {
373 		fprintf(stderr, "Cannot copy value:\n  %s\n",
374 			avro_strerror());
375 		return EXIT_FAILURE;
376 	}
377 
378 	if (!avro_value_equal(val, &copied_val)) {
379 		fprintf(stderr, "Copied values not equal\n");
380 		return EXIT_FAILURE;
381 	}
382 
383 	check_hash(val, &copied_val);
384 
385 	avro_value_decref(&copied_val);
386 	return EXIT_SUCCESS;
387 }
388 
389 #define check_copy(val) \
390 	check_(_check_copy(val))
391 
392 static int
test_boolean(void)393 test_boolean(void)
394 {
395 	int  rval;
396 
397 	int  i;
398 	for (i = 0; i <= 1; i++) {
399 		avro_value_t  val;
400 		try(avro_generic_boolean_new(&val, i),
401 		    "Cannot create boolean");
402 		check(rval, check_type_and_schema
403 			    ("boolean", &val,
404 			     AVRO_BOOLEAN, avro_schema_boolean()));
405 		try(avro_value_reset(&val),
406 		    "Cannot reset boolean");
407 		try(avro_value_set_boolean(&val, i),
408 		    "Cannot set boolean");
409 
410 		/* Start with the wrong value to make sure _get does
411 		 * something. */
412 		int  actual = (int) 23;
413 		try(avro_value_get_boolean(&val, &actual),
414 		    "Cannot get boolean value");
415 
416 		if (actual != i) {
417 			fprintf(stderr, "Unexpected boolean value\n");
418 			return EXIT_FAILURE;
419 		}
420 
421 		check_invalid_methods("boolean", &val);
422 		check_write_read(&val);
423 		check_copy(&val);
424 		avro_value_decref(&val);
425 	}
426 
427 	avro_value_t  val1;
428 	avro_value_t  val2;
429 	try(avro_generic_boolean_new(&val1, 0),
430 	    "Cannot create boolean");
431 	try(avro_generic_boolean_new(&val2, 1),
432 	    "Cannot create boolean");
433 	if (avro_value_cmp_fast(&val1, &val2) >= 0) {
434 		fprintf(stderr, "Incorrect sort order\n");
435 		return EXIT_FAILURE;
436 	}
437 	if (avro_value_cmp_fast(&val2, &val1) <= 0) {
438 		fprintf(stderr, "Incorrect sort order\n");
439 		return EXIT_FAILURE;
440 	}
441 	if (avro_value_cmp_fast(&val1, &val1) != 0) {
442 		fprintf(stderr, "Incorrect sort order\n");
443 		return EXIT_FAILURE;
444 	}
445 	avro_value_decref(&val1);
446 	avro_value_decref(&val2);
447 
448 	return 0;
449 }
450 
451 static int
test_bytes(void)452 test_bytes(void)
453 {
454 	int  rval;
455 
456 	char bytes[] = { 0xDE, 0xAD, 0xBE, 0xEF };
457 
458 	avro_value_t  val;
459 	try(avro_generic_bytes_new(&val, bytes, sizeof(bytes)),
460 	    "Cannot create bytes");
461 	check(rval, check_type_and_schema
462 		    ("bytes", &val,
463 		     AVRO_BYTES, avro_schema_bytes()));
464 	try(avro_value_reset(&val),
465 	    "Cannot reset bytes");
466 	try(avro_value_set_bytes(&val, bytes, sizeof(bytes)),
467 	    "Cannot set bytes");
468 
469 	const void  *actual_buf = NULL;
470 	size_t  actual_size = 0;
471 	try(avro_value_get_bytes(&val, &actual_buf, &actual_size),
472 	    "Cannot get bytes value");
473 
474 	if (actual_size != sizeof(bytes)) {
475 		fprintf(stderr, "Unexpected bytes size\n");
476 		return EXIT_FAILURE;
477 	}
478 
479 	if (memcmp(actual_buf, bytes, sizeof(bytes)) != 0) {
480 		fprintf(stderr, "Unexpected bytes contents\n");
481 		return EXIT_FAILURE;
482 	}
483 
484 	avro_wrapped_buffer_t  wbuf;
485 	try(avro_value_grab_bytes(&val, &wbuf),
486 	    "Cannot grab bytes value");
487 
488 	if (wbuf.size != sizeof(bytes)) {
489 		fprintf(stderr, "Unexpected grabbed bytes size\n");
490 		return EXIT_FAILURE;
491 	}
492 
493 	if (memcmp(wbuf.buf, bytes, sizeof(bytes)) != 0) {
494 		fprintf(stderr, "Unexpected grabbed bytes contents\n");
495 		return EXIT_FAILURE;
496 	}
497 
498 	avro_wrapped_buffer_free(&wbuf);
499 
500 	check_invalid_methods("bytes", &val);
501 	check_write_read(&val);
502 	check_copy(&val);
503 	avro_value_decref(&val);
504 
505 	avro_value_t  val1;
506 	avro_value_t  val2;
507 	avro_value_t  val3;
508 	try(avro_generic_bytes_new(&val1, "abcd", 4),
509 	    "Cannot create bytes");
510 	try(avro_generic_bytes_new(&val2, "abcde", 5),
511 	    "Cannot create bytes");
512 	try(avro_generic_bytes_new(&val3, "abce", 4),
513 	    "Cannot create bytes");
514 	if (avro_value_cmp_fast(&val1, &val2) >= 0) {
515 		fprintf(stderr, "Incorrect sort order\n");
516 		return EXIT_FAILURE;
517 	}
518 	if (avro_value_cmp_fast(&val2, &val1) <= 0) {
519 		fprintf(stderr, "Incorrect sort order\n");
520 		return EXIT_FAILURE;
521 	}
522 	if (avro_value_cmp_fast(&val1, &val3) >= 0) {
523 		fprintf(stderr, "Incorrect sort order\n");
524 		return EXIT_FAILURE;
525 	}
526 	if (avro_value_cmp_fast(&val1, &val1) != 0) {
527 		fprintf(stderr, "Incorrect sort order\n");
528 		return EXIT_FAILURE;
529 	}
530 	avro_value_decref(&val1);
531 	avro_value_decref(&val2);
532 	avro_value_decref(&val3);
533 
534 	return 0;
535 }
536 
537 static int
test_double(void)538 test_double(void)
539 {
540 	int  rval;
541 
542 	int  i;
543 	for (i = 0; i < 100; i++) {
544 		double  expected = rand_number(-1e10, 1e10);
545 		avro_value_t  val;
546 		try(avro_generic_double_new(&val, expected),
547 		    "Cannot create double");
548 		check(rval, check_type_and_schema
549 			    ("double", &val,
550 			     AVRO_DOUBLE, avro_schema_double()));
551 		try(avro_value_reset(&val),
552 		    "Cannot reset double");
553 		try(avro_value_set_double(&val, expected),
554 		    "Cannot set double");
555 
556 		double  actual = 0.0;
557 		try(avro_value_get_double(&val, &actual),
558 		    "Cannot get double value");
559 
560 		if (actual != expected) {
561 			fprintf(stderr, "Unexpected double value\n");
562 			return EXIT_FAILURE;
563 		}
564 
565 		check_invalid_methods("double", &val);
566 		check_write_read(&val);
567 		check_copy(&val);
568 		avro_value_decref(&val);
569 	}
570 	return 0;
571 }
572 
573 static int
test_float(void)574 test_float(void)
575 {
576 	int  rval;
577 
578 	int  i;
579 	for (i = 0; i < 100; i++) {
580 		float  expected = rand_number(-1e10, 1e10);
581 		avro_value_t  val;
582 		try(avro_generic_float_new(&val, expected),
583 		    "Cannot create float");
584 		check(rval, check_type_and_schema
585 			    ("float", &val,
586 			     AVRO_FLOAT, avro_schema_float()));
587 		try(avro_value_reset(&val),
588 		    "Cannot reset float");
589 		try(avro_value_set_float(&val, expected),
590 		    "Cannot set float");
591 
592 		float  actual = 0.0f;
593 		try(avro_value_get_float(&val, &actual),
594 		    "Cannot get float value");
595 
596 		if (actual != expected) {
597 			fprintf(stderr, "Unexpected float value\n");
598 			return EXIT_FAILURE;
599 		}
600 
601 		check_invalid_methods("float", &val);
602 		check_write_read(&val);
603 		check_copy(&val);
604 		avro_value_decref(&val);
605 	}
606 	return 0;
607 }
608 
609 static int
test_int(void)610 test_int(void)
611 {
612 	int  rval;
613 
614 	int  i;
615 	for (i = 0; i < 100; i++) {
616 		int32_t  expected = rand_int32();
617 		avro_value_t  val;
618 		try(avro_generic_int_new(&val, expected),
619 		    "Cannot create int");
620 		check(rval, check_type_and_schema
621 			    ("int", &val,
622 			     AVRO_INT32, avro_schema_int()));
623 		try(avro_value_reset(&val),
624 		    "Cannot reset int");
625 		try(avro_value_set_int(&val, expected),
626 		    "Cannot set int");
627 
628 		int32_t  actual = 0;
629 		try(avro_value_get_int(&val, &actual),
630 		    "Cannot get int value");
631 
632 		if (actual != expected) {
633 			fprintf(stderr, "Unexpected int value\n");
634 			return EXIT_FAILURE;
635 		}
636 
637 		check_invalid_methods("int", &val);
638 		check_write_read(&val);
639 		check_copy(&val);
640 		avro_value_decref(&val);
641 	}
642 
643 	avro_value_t  val1;
644 	avro_value_t  val2;
645 	try(avro_generic_int_new(&val1, -10),
646 	    "Cannot create int");
647 	try(avro_generic_int_new(&val2, 42),
648 	    "Cannot create int");
649 	if (avro_value_cmp_fast(&val1, &val2) >= 0) {
650 		fprintf(stderr, "Incorrect sort order\n");
651 		return EXIT_FAILURE;
652 	}
653 	if (avro_value_cmp_fast(&val2, &val1) <= 0) {
654 		fprintf(stderr, "Incorrect sort order\n");
655 		return EXIT_FAILURE;
656 	}
657 	if (avro_value_cmp_fast(&val1, &val1) != 0) {
658 		fprintf(stderr, "Incorrect sort order\n");
659 		return EXIT_FAILURE;
660 	}
661 	avro_value_decref(&val1);
662 	avro_value_decref(&val2);
663 
664 	return 0;
665 }
666 
667 static int
test_long(void)668 test_long(void)
669 {
670 	int  rval;
671 
672 	int  i;
673 	for (i = 0; i < 100; i++) {
674 		int64_t  expected = rand_int64();
675 		avro_value_t  val;
676 		try(avro_generic_long_new(&val, expected),
677 		    "Cannot create long");
678 		check(rval, check_type_and_schema
679 			    ("long", &val,
680 			     AVRO_INT64, avro_schema_long()));
681 		try(avro_value_reset(&val),
682 		    "Cannot reset long");
683 		try(avro_value_set_long(&val, expected),
684 		    "Cannot set long");
685 
686 		int64_t  actual = 0;
687 		try(avro_value_get_long(&val, &actual),
688 		    "Cannot get long value");
689 
690 		if (actual != expected) {
691 			fprintf(stderr, "Unexpected long value\n");
692 			return EXIT_FAILURE;
693 		}
694 
695 		check_invalid_methods("long", &val);
696 		check_write_read(&val);
697 		check_copy(&val);
698 		avro_value_decref(&val);
699 	}
700 	return 0;
701 }
702 
703 static int
test_null(void)704 test_null(void)
705 {
706 	int  rval;
707 
708 	avro_value_t  val;
709 	try(avro_generic_null_new(&val),
710 	    "Cannot create null");
711 	check(rval, check_type_and_schema
712 		    ("null", &val,
713 		     AVRO_NULL, avro_schema_null()));
714 	try(avro_value_reset(&val),
715 	    "Cannot reset null");
716 	try(avro_value_set_null(&val),
717 	    "Cannot set null");
718 	try(avro_value_get_null(&val),
719 	    "Cannot get null");
720 
721 	check_invalid_methods("null", &val);
722 	check_write_read(&val);
723 	check_copy(&val);
724 	avro_value_decref(&val);
725 	return 0;
726 }
727 
728 static int
test_string(void)729 test_string(void)
730 {
731 	int  rval;
732 
733 	char *strings[] = {
734 		"Four score and seven years ago",
735 		"our father brought forth on this continent",
736 		"a new nation",
737 		"conceived in Liberty",
738 		"and dedicated to the proposition that all men "
739 			"are created equal."
740 	};
741 
742 	unsigned int  i;
743 	for (i = 0; i < sizeof(strings) / sizeof(strings[0]); i++) {
744 		avro_value_t  val;
745 		try(avro_generic_string_new(&val, strings[i]),
746 		    "Cannot create string");
747 		check(rval, check_type_and_schema
748 			    ("string", &val,
749 			     AVRO_STRING, avro_schema_string()));
750 		try(avro_value_reset(&val),
751 		    "Cannot reset string");
752 		try(avro_value_set_string_len(&val, "", 0),
753 		    "Cannot set_len dummy string");
754 
755 		/* First try a round-trip using set_string */
756 
757 		try(avro_value_set_string(&val, strings[i]),
758 		    "Cannot set string");
759 
760 		const char  *actual_str = NULL;
761 		size_t  actual_size = 0;
762 		try(avro_value_get_string(&val, &actual_str, &actual_size),
763 		    "Cannot get string value");
764 
765 		if (actual_size != strlen(strings[i])+1) {
766 			fprintf(stderr, "Unexpected string size\n");
767 			return EXIT_FAILURE;
768 		}
769 
770 		if (strcmp(actual_str, strings[i]) != 0) {
771 			fprintf(stderr, "Unexpected string contents\n");
772 			return EXIT_FAILURE;
773 		}
774 
775 		avro_wrapped_buffer_t  wbuf;
776 		try(avro_value_grab_string(&val, &wbuf),
777 		    "Cannot grab string value");
778 
779 		if (wbuf.size != strlen(strings[i])+1) {
780 			fprintf(stderr, "Unexpected grabbed string size\n");
781 			return EXIT_FAILURE;
782 		}
783 
784 		if (strcmp((const char *) wbuf.buf, strings[i]) != 0) {
785 			fprintf(stderr, "Unexpected grabbed string contents\n");
786 			return EXIT_FAILURE;
787 		}
788 
789 		avro_wrapped_buffer_free(&wbuf);
790 
791 		/* and then again using set_string_len */
792 
793 		size_t  str_length = strlen(strings[i])+1;
794 		try(avro_value_set_string_len(&val, strings[i], str_length),
795 		    "Cannot set_len string");
796 
797 		actual_str = NULL;
798 		actual_size = 0;
799 		try(avro_value_get_string(&val, &actual_str, &actual_size),
800 		    "Cannot get string value");
801 
802 		if (actual_size != strlen(strings[i])+1) {
803 			fprintf(stderr, "Unexpected string size\n");
804 			return EXIT_FAILURE;
805 		}
806 
807 		if (strcmp(actual_str, strings[i]) != 0) {
808 			fprintf(stderr, "Unexpected string contents\n");
809 			return EXIT_FAILURE;
810 		}
811 
812 		try(avro_value_grab_string(&val, &wbuf),
813 		    "Cannot grab string value");
814 
815 		if (wbuf.size != strlen(strings[i])+1) {
816 			fprintf(stderr, "Unexpected grabbed string size\n");
817 			return EXIT_FAILURE;
818 		}
819 
820 		if (strcmp((const char *) wbuf.buf, strings[i]) != 0) {
821 			fprintf(stderr, "Unexpected grabbed string contents\n");
822 			return EXIT_FAILURE;
823 		}
824 
825 		avro_wrapped_buffer_free(&wbuf);
826 
827 		check_invalid_methods("string", &val);
828 		check_write_read(&val);
829 		check_copy(&val);
830 		avro_value_decref(&val);
831 	}
832 
833 	return 0;
834 }
835 
836 static int
test_array(void)837 test_array(void)
838 {
839 	avro_schema_t  double_schema = avro_schema_double();
840 	avro_schema_t  array_schema = avro_schema_array(double_schema);
841 
842 	avro_value_iface_t  *array_class =
843 	    avro_generic_class_from_schema(array_schema);
844 
845 	int  rval;
846 
847 	int  i;
848 	for (i = 0; i < 100; i++) {
849 		size_t  count = rand_count();
850 
851 		avro_value_t  val;
852 		try(avro_generic_value_new(array_class, &val),
853 		    "Cannot create array");
854 		check(rval, check_type_and_schema
855 			    ("array", &val, AVRO_ARRAY,
856 			     avro_schema_incref(array_schema)));
857 
858 		size_t  j;
859 		for (j = 0; j < count; j++) {
860 			avro_value_t  element;
861 			size_t  new_index;
862 			try(avro_value_append(&val, &element, &new_index),
863 			    "Cannot append to array");
864 			if (new_index != j) {
865 				fprintf(stderr, "Unexpected index\n");
866 				return EXIT_FAILURE;
867 			}
868 
869 			double  expected = rand_number(-1e10, 1e10);
870 			try(avro_value_set_double(&element, expected),
871 			    "Cannot set double");
872 			try(avro_value_get_by_index(&val, j, &element, NULL),
873 			    "Cannot get from array");
874 
875 			double  actual = 0.0;
876 			try(avro_value_get_double(&element, &actual),
877 			    "Cannot get double value");
878 
879 			if (actual != expected) {
880 				fprintf(stderr, "Unexpected double value\n");
881 				return EXIT_FAILURE;
882 			}
883 		}
884 
885 		size_t  actual_size = 0;
886 		try(avro_value_get_size(&val, &actual_size),
887 		    "Cannot get_size array");
888 
889 		if (actual_size != count) {
890 			fprintf(stderr, "Unexpected size\n");
891 			return EXIT_FAILURE;
892 		}
893 
894 		check_write_read(&val);
895 		check_copy(&val);
896 
897 		try(avro_value_reset(&val),
898 		    "Cannot reset array");
899 		try(avro_value_get_size(&val, &actual_size),
900 		    "Cannot get_size empty array");
901 
902 		if (actual_size != 0) {
903 			fprintf(stderr, "Unexpected empty size\n");
904 			return EXIT_FAILURE;
905 		}
906 
907 		check_invalid_methods("array", &val);
908 		avro_value_decref(&val);
909 	}
910 
911 	avro_schema_decref(double_schema);
912 	avro_schema_decref(array_schema);
913 	avro_value_iface_decref(array_class);
914 	return 0;
915 }
916 
917 static int
test_enum(void)918 test_enum(void)
919 {
920 	static const char  SCHEMA_JSON[] =
921 	"{"
922 	"  \"type\": \"enum\","
923 	"  \"name\": \"suits\","
924 	"  \"symbols\": [\"CLUBS\",\"DIAMONDS\",\"HEARTS\",\"SPADES\"]"
925 	"}";
926 
927 	avro_schema_t  enum_schema = NULL;
928 	if (avro_schema_from_json_literal(SCHEMA_JSON, &enum_schema)) {
929 		fprintf(stderr, "Error parsing schema:\n  %s\n",
930 			avro_strerror());
931 		return EXIT_FAILURE;
932 	}
933 
934 	avro_value_iface_t  *enum_class =
935 	    avro_generic_class_from_schema(enum_schema);
936 
937 	int  rval;
938 
939 	int  i;
940 	for (i = 0; i < 4; i++) {
941 		int  expected = i;
942 		avro_value_t  val;
943 		try(avro_generic_value_new(enum_class, &val),
944 		    "Cannot create enum");
945 		check(rval, check_type_and_schema
946 			    ("enum", &val, AVRO_ENUM,
947 			     avro_schema_incref(enum_schema)));
948 		try(avro_value_reset(&val),
949 		    "Cannot reset enum");
950 		try(avro_value_set_enum(&val, expected),
951 		    "Cannot set enum");
952 
953 		int  actual = -1;
954 		try(avro_value_get_enum(&val, &actual),
955 		    "Cannot get enum value");
956 
957 		if (actual != expected) {
958 			fprintf(stderr, "Unexpected enum value\n");
959 			return EXIT_FAILURE;
960 		}
961 
962 		check_invalid_methods("enum", &val);
963 		check_write_read(&val);
964 		check_copy(&val);
965 		avro_value_decref(&val);
966 	}
967 
968 	avro_schema_decref(enum_schema);
969 	avro_value_iface_decref(enum_class);
970 	return 0;
971 }
972 
973 static int
test_fixed(void)974 test_fixed(void)
975 {
976 	static const char  SCHEMA_JSON[] =
977 	"{"
978 	"  \"type\": \"fixed\","
979 	"  \"name\": \"ipv4\","
980 	"  \"size\": 4"
981 	"}";
982 
983 	avro_schema_t  fixed_schema = NULL;
984 	if (avro_schema_from_json_literal(SCHEMA_JSON, &fixed_schema)) {
985 		fprintf(stderr, "Error parsing schema:\n  %s\n",
986 			avro_strerror());
987 		return EXIT_FAILURE;
988 	}
989 
990 	avro_value_iface_t  *fixed_class =
991 	    avro_generic_class_from_schema(fixed_schema);
992 
993 	int  rval;
994 
995 	char fixed[] = { 0xDE, 0xAD, 0xBE, 0xEF };
996 
997 	avro_value_t  val;
998 	try(avro_generic_value_new(fixed_class, &val),
999 	    "Cannot create fixed");
1000 	check(rval, check_type_and_schema
1001 		    ("fixed", &val, AVRO_FIXED,
1002 		     avro_schema_incref(fixed_schema)));
1003 	try(avro_value_reset(&val),
1004 	    "Cannot reset fixed");
1005 
1006 	/* verify an error on invalid size */
1007 	try(!avro_value_set_fixed(&val, fixed, 0),
1008 	    "Expected error with invalid size");
1009 
1010 	try(avro_value_set_fixed(&val, fixed, sizeof(fixed)),
1011 	    "Cannot set fixed");
1012 
1013 	const void  *actual_buf = NULL;
1014 	size_t  actual_size = 0;
1015 	try(avro_value_get_fixed(&val, &actual_buf, &actual_size),
1016 	    "Cannot get fixed value");
1017 
1018 	if (actual_size != sizeof(fixed)) {
1019 		fprintf(stderr, "Unexpected fixed size\n");
1020 		return EXIT_FAILURE;
1021 	}
1022 
1023 	if (memcmp(actual_buf, fixed, sizeof(fixed)) != 0) {
1024 		fprintf(stderr, "Unexpected fixed contents\n");
1025 		return EXIT_FAILURE;
1026 	}
1027 
1028 	avro_wrapped_buffer_t  wbuf;
1029 	try(avro_value_grab_fixed(&val, &wbuf),
1030 	    "Cannot grab fixed value");
1031 
1032 	if (wbuf.size != sizeof(fixed)) {
1033 		fprintf(stderr, "Unexpected grabbed fixed size\n");
1034 		return EXIT_FAILURE;
1035 	}
1036 
1037 	if (memcmp(wbuf.buf, fixed, sizeof(fixed)) != 0) {
1038 		fprintf(stderr, "Unexpected grabbed fixed contents\n");
1039 		return EXIT_FAILURE;
1040 	}
1041 
1042 	avro_wrapped_buffer_free(&wbuf);
1043 
1044 	check_invalid_methods("fixed", &val);
1045 	check_write_read(&val);
1046 	check_copy(&val);
1047 	avro_value_decref(&val);
1048 	avro_schema_decref(fixed_schema);
1049 	avro_value_iface_decref(fixed_class);
1050 	return 0;
1051 }
1052 
1053 static int
test_map(void)1054 test_map(void)
1055 {
1056 	avro_schema_t  double_schema = avro_schema_double();
1057 	avro_schema_t  map_schema = avro_schema_map(double_schema);
1058 
1059 	avro_value_iface_t  *map_class =
1060 	    avro_generic_class_from_schema(map_schema);
1061 
1062 	int  rval;
1063 
1064 	int  i;
1065 	for (i = 0; i < 100; i++) {
1066 		size_t  count = rand_count();
1067 
1068 		avro_value_t  val;
1069 		try(avro_generic_value_new(map_class, &val),
1070 		    "Cannot create map");
1071 		check(rval, check_type_and_schema
1072 			    ("map", &val, AVRO_MAP,
1073 			     avro_schema_incref(map_schema)));
1074 
1075 		size_t  j;
1076 		for (j = 0; j < count; j++) {
1077 			avro_value_t  element;
1078 			size_t  new_index;
1079 			int  is_new = 0;
1080 
1081 			char  key[64];
1082 			snprintf(key, 64, "%" PRIsz, j);
1083 
1084 			try(avro_value_add(&val, key,
1085 					   &element, &new_index, &is_new),
1086 			    "Cannot add to map");
1087 
1088 			if (new_index != j) {
1089 				fprintf(stderr, "Unexpected index\n");
1090 				return EXIT_FAILURE;
1091 			}
1092 
1093 			if (!is_new) {
1094 				fprintf(stderr, "Expected new element\n");
1095 				return EXIT_FAILURE;
1096 			}
1097 
1098 			double  expected = rand_number(-1e10, 1e10);
1099 			try(avro_value_set_double(&element, expected),
1100 			    "Cannot set double");
1101 			try(avro_value_add(&val, key,
1102 					   &element, &new_index, &is_new),
1103 			    "Cannot re-add to map");
1104 
1105 			if (is_new) {
1106 				fprintf(stderr, "Expected non-new element\n");
1107 				return EXIT_FAILURE;
1108 			}
1109 
1110 			const char  *actual_key = NULL;
1111 			try(avro_value_get_by_index(&val, j, &element,
1112 						    &actual_key),
1113 			    "Cannot get from map");
1114 
1115 			if (strcmp(actual_key, key) != 0) {
1116 				fprintf(stderr, "Unexpected key\n");
1117 				return EXIT_FAILURE;
1118 			}
1119 
1120 			double  actual = 0.0;
1121 			try(avro_value_get_double(&element, &actual),
1122 			    "Cannot get double value");
1123 
1124 			if (actual != expected) {
1125 				fprintf(stderr, "Unexpected double value\n");
1126 				return EXIT_FAILURE;
1127 			}
1128 		}
1129 
1130 		size_t  actual_size = 0;
1131 		try(avro_value_get_size(&val, &actual_size),
1132 		    "Cannot get_size map");
1133 
1134 		if (actual_size != count) {
1135 			fprintf(stderr, "Unexpected size\n");
1136 			return EXIT_FAILURE;
1137 		}
1138 
1139 		/*
1140 		 * Create a reversed copy of the map to ensure that the
1141 		 * element ordering doesn't affect the hash value.
1142 		 */
1143 
1144 		avro_value_t  reversed;
1145 		try(avro_generic_value_new(map_class, &reversed),
1146 		    "Cannot create map");
1147 
1148 		for (j = count; j-- > 0; ) {
1149 			avro_value_t  element;
1150 			const char  *key = NULL;
1151 			double  element_value = 0.0;
1152 			try(avro_value_get_by_index(&val, j, &element, &key),
1153 			    "Cannot get from map");
1154 			try(avro_value_get_double(&element, &element_value),
1155 			    "Cannot get double value");
1156 
1157 			try(avro_value_add(&reversed, key, &element, NULL, NULL),
1158 			    "Cannot add to map");
1159 			try(avro_value_set_double(&element, element_value),
1160 			    "Cannot set double");
1161 		}
1162 
1163 		check_hash(&val, &reversed);
1164 		if (!avro_value_equal(&val, &reversed)) {
1165 			fprintf(stderr, "Reversed values not equal\n");
1166 			return EXIT_FAILURE;
1167 		}
1168 
1169 		/* Final tests and cleanup */
1170 
1171 		check_write_read(&val);
1172 		check_copy(&val);
1173 
1174 		try(avro_value_reset(&val),
1175 		    "Cannot reset map");
1176 		try(avro_value_get_size(&val, &actual_size),
1177 		    "Cannot get_size empty map");
1178 
1179 		if (actual_size != 0) {
1180 			fprintf(stderr, "Unexpected empty size\n");
1181 			return EXIT_FAILURE;
1182 		}
1183 
1184 		check_invalid_methods("map", &val);
1185 		avro_value_decref(&val);
1186 		avro_value_decref(&reversed);
1187 	}
1188 
1189 	avro_schema_decref(double_schema);
1190 	avro_schema_decref(map_schema);
1191 	avro_value_iface_decref(map_class);
1192 	return 0;
1193 }
1194 
1195 static int
test_record(void)1196 test_record(void)
1197 {
1198 	static const char  SCHEMA_JSON[] =
1199 	"{"
1200 	"  \"type\": \"record\","
1201 	"  \"name\": \"test\","
1202 	"  \"fields\": ["
1203 	"    { \"name\": \"b\", \"type\": \"boolean\" },"
1204 	"    { \"name\": \"i\", \"type\": \"int\" },"
1205 	"    { \"name\": \"s\", \"type\": \"string\" },"
1206 	"    { \"name\": \"ds\", \"type\": "
1207 	"      { \"type\": \"array\", \"items\": \"double\" } },"
1208 	"    { \"name\": \"sub\", \"type\": "
1209 	"      {"
1210 	"        \"type\": \"record\","
1211 	"        \"name\": \"subtest\","
1212 	"        \"fields\": ["
1213 	"          { \"name\": \"f\", \"type\": \"float\" },"
1214 	"          { \"name\": \"l\", \"type\": \"long\" }"
1215 	"        ]"
1216 	"      }"
1217 	"    },"
1218 	"    { \"name\": \"nested\", \"type\": [\"null\", \"test\"] }"
1219 	"  ]"
1220 	"}";
1221 
1222 	avro_schema_t  record_schema = NULL;
1223 	if (avro_schema_from_json_literal(SCHEMA_JSON, &record_schema)) {
1224 		fprintf(stderr, "Error parsing schema:\n  %s\n",
1225 			avro_strerror());
1226 		return EXIT_FAILURE;
1227 	}
1228 
1229 	avro_value_iface_t  *record_class =
1230 	    avro_generic_class_from_schema(record_schema);
1231 
1232 	int  rval;
1233 
1234 	avro_value_t  val;
1235 	try(avro_generic_value_new(record_class, &val),
1236 	    "Cannot create record");
1237 	check(rval, check_type_and_schema
1238 		    ("record", &val, AVRO_RECORD,
1239 		     avro_schema_incref(record_schema)));
1240 
1241 	size_t  field_count;
1242 	try(avro_value_get_size(&val, &field_count),
1243 	    "Cannot get field count");
1244 	if (field_count != 6) {
1245 		fprintf(stderr, "Unexpected field count\n");
1246 		return EXIT_FAILURE;
1247 	}
1248 
1249 	/* Assign to each field */
1250 	avro_value_t  field;
1251 	avro_value_t  element;
1252 	avro_value_t  subfield;
1253 	avro_value_t  branch;
1254 	const char  *name;
1255 	size_t  index;
1256 
1257 	try(avro_value_get_by_index(&val, 0, &field, NULL),
1258 	    "Cannot get field 0");
1259 	try(avro_value_set_boolean(&field, 1),
1260 	    "Cannot set field 0");
1261 
1262 	try(avro_value_get_by_index(&val, 1, &field, &name),
1263 	    "Cannot get field 1");
1264 	try(avro_value_set_int(&field, 42),
1265 	    "Cannot set field 1");
1266 	if (strcmp(name, "i") != 0) {
1267 		fprintf(stderr, "Unexpected name for field 1: %s\n", name);
1268 		return EXIT_FAILURE;
1269 	}
1270 
1271 	try(avro_value_get_by_index(&val, 2, &field, NULL),
1272 	    "Cannot get field 2");
1273 	try(avro_value_set_string(&field, "Hello world!"),
1274 	    "Cannot set field 2");
1275 
1276 	try(avro_value_get_by_name(&val, "i", &field, &index),
1277 	    "Cannot get \"i\" field");
1278 	if (index != 1) {
1279 		fprintf(stderr, "Unexpected index for \"i\" field: %" PRIsz "\n", index);
1280 		return EXIT_FAILURE;
1281 	}
1282 
1283 	try(avro_value_get_by_index(&val, 3, &field, NULL),
1284 	    "Cannot get field 3");
1285 	try(avro_value_append(&field, &element, NULL),
1286 	    "Cannot append to field 3");
1287 	try(avro_value_set_double(&element, 10.0),
1288 	    "Cannot set field 3, element 0");
1289 
1290 	try(avro_value_get_by_index(&val, 4, &field, NULL),
1291 	    "Cannot get field 4");
1292 
1293 	try(avro_value_get_by_index(&field, 0, &subfield, NULL),
1294 	    "Cannot get field 4, subfield 0");
1295 	try(avro_value_set_float(&subfield, 5.0f),
1296 	    "Cannot set field 4, subfield 0");
1297 
1298 	try(avro_value_get_by_index(&field, 1, &subfield, NULL),
1299 	    "Cannot get field 4, subfield 1");
1300 	try(avro_value_set_long(&subfield, 10000),
1301 	    "Cannot set field 4, subfield 1");
1302 
1303 	try(avro_value_get_by_index(&val, 5, &field, NULL),
1304 	    "Cannot get field 5");
1305 	try(avro_value_set_branch(&field, 0, &branch),
1306 	    "Cannot select null branch");
1307 
1308 	check_write_read(&val);
1309 	check_copy(&val);
1310 
1311 	/* Reset and verify that the fields are empty again */
1312 	try(avro_value_reset(&val),
1313 	    "Cannot reset record");
1314 
1315 	int  bval;
1316 	try(avro_value_get_by_index(&val, 0, &field, NULL),
1317 	    "Cannot get field 0");
1318 	try(avro_value_get_boolean(&field, &bval),
1319 	    "Cannot get field 0 value");
1320 	if (bval) {
1321 		fprintf(stderr, "Unexpected value for field 0\n");
1322 		return EXIT_FAILURE;
1323 	}
1324 
1325 	size_t  count;
1326 	try(avro_value_get_by_index(&val, 3, &field, NULL),
1327 	    "Cannot get field 3");
1328 	try(avro_value_get_size(&field, &count),
1329 	    "Cannot get field 3 size");
1330 	if (count != 0) {
1331 		fprintf(stderr, "Unexpected size for field 3\n");
1332 		return EXIT_FAILURE;
1333 	}
1334 
1335 	check_invalid_methods("record", &val);
1336 	avro_value_decref(&val);
1337 	avro_value_iface_decref(record_class);
1338 	avro_schema_decref(record_schema);
1339 	return EXIT_SUCCESS;
1340 }
1341 
1342 static int
test_union(void)1343 test_union(void)
1344 {
1345 	static const char  SCHEMA_JSON[] =
1346 	"["
1347 	"  \"null\","
1348 	"  \"int\","
1349 	"  \"double\","
1350 	"  \"bytes\""
1351 	"]";
1352 
1353 	avro_schema_t  union_schema = NULL;
1354 	if (avro_schema_from_json_literal(SCHEMA_JSON, &union_schema)) {
1355 		fprintf(stderr, "Error parsing schema:\n  %s\n",
1356 			avro_strerror());
1357 		return EXIT_FAILURE;
1358 	}
1359 
1360 	avro_value_iface_t  *union_class =
1361 	    avro_generic_class_from_schema(union_schema);
1362 
1363 	int  rval;
1364 
1365 	avro_value_t  val;
1366 	try(avro_generic_value_new(union_class, &val),
1367 	    "Cannot create union");
1368 	check(rval, check_type_and_schema
1369 		    ("union", &val, AVRO_UNION,
1370 		     avro_schema_incref(union_schema)));
1371 
1372 	int discriminant = 0;
1373 	try(avro_value_get_discriminant(&val, &discriminant),
1374 	    "Cannot get union discriminant");
1375 
1376 	if (discriminant != -1) {
1377 		fprintf(stderr, "Unexpected union discriminant\n");
1378 		return EXIT_FAILURE;
1379 	}
1380 
1381 	avro_value_t  branch;
1382 	try(!avro_value_get_current_branch(&val, &branch),
1383 	    "Expected error getting empty current branch");
1384 
1385 	try(avro_value_set_branch(&val, 0, &branch),
1386 	    "Cannot select null branch");
1387 	try(avro_value_set_null(&branch),
1388 	    "Cannot set null branch value");
1389 
1390 	try(avro_value_set_branch(&val, 1, &branch),
1391 	    "Cannot select int branch");
1392 	try(avro_value_set_int(&branch, 42),
1393 	    "Cannot set int branch value");
1394 
1395 	try(avro_value_set_branch(&val, 1, &branch),
1396 	    "Cannot select int branch");
1397 	try(avro_value_set_int(&branch, 10),
1398 	    "Cannot set int branch value");
1399 
1400 	try(avro_value_set_branch(&val, 2, &branch),
1401 	    "Cannot select double branch");
1402 	try(avro_value_set_double(&branch, 10.0),
1403 	    "Cannot set double branch value");
1404 
1405 	char bytes[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1406 	try(avro_value_set_branch(&val, 3, &branch),
1407 	    "Cannot select bytes branch");
1408 	try(avro_value_set_bytes(&branch, bytes, sizeof(bytes)),
1409 	    "Cannot set bytes branch value");
1410 
1411 	check_invalid_methods("union", &val);
1412 	check_write_read(&val);
1413 	check_copy(&val);
1414 	avro_value_decref(&val);
1415 
1416 	avro_schema_decref(union_schema);
1417 	avro_value_iface_decref(union_class);
1418 	return 0;
1419 }
1420 
main(void)1421 int main(void)
1422 {
1423 	avro_set_allocator(test_allocator, NULL);
1424 
1425 	unsigned int i;
1426 	struct avro_tests {
1427 		char *name;
1428 		avro_test func;
1429 	} tests[] = {
1430 		{ "boolean", test_boolean },
1431 		{ "bytes", test_bytes },
1432 		{ "double", test_double },
1433 		{ "float", test_float },
1434 		{ "int", test_int },
1435 		{ "long", test_long },
1436 		{ "null", test_null },
1437 		{ "string", test_string },
1438 		{ "array", test_array },
1439 		{ "enum", test_enum },
1440 		{ "fixed", test_fixed },
1441 		{ "map", test_map },
1442 		{ "record", test_record },
1443 		{ "union", test_union }
1444 	};
1445 
1446 	init_rand();
1447 	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
1448 		struct avro_tests *test = tests + i;
1449 		fprintf(stderr, "**** Running %s tests ****\n", test->name);
1450 		if (test->func() != 0) {
1451 			return EXIT_FAILURE;
1452 		}
1453 	}
1454 	return EXIT_SUCCESS;
1455 }
1456