stress-test.c revision 6ba797d6
1#include <stdio.h>
2#include "utils.h"
3#include <sys/types.h>
4
5#if 0
6#define fence_malloc malloc
7#define fence_free free
8#define make_random_bytes malloc
9#endif
10
11static const pixman_format_code_t image_formats[] =
12{
13    PIXMAN_a8r8g8b8,
14    PIXMAN_x8r8g8b8,
15    PIXMAN_r5g6b5,
16    PIXMAN_r3g3b2,
17    PIXMAN_a8,
18    PIXMAN_a8b8g8r8,
19    PIXMAN_x8b8g8r8,
20    PIXMAN_b8g8r8a8,
21    PIXMAN_b8g8r8x8,
22    PIXMAN_r8g8b8a8,
23    PIXMAN_r8g8b8x8,
24    PIXMAN_x14r6g6b6,
25    PIXMAN_r8g8b8,
26    PIXMAN_b8g8r8,
27    PIXMAN_r5g6b5,
28    PIXMAN_b5g6r5,
29    PIXMAN_x2r10g10b10,
30    PIXMAN_a2r10g10b10,
31    PIXMAN_x2b10g10r10,
32    PIXMAN_a2b10g10r10,
33    PIXMAN_a1r5g5b5,
34    PIXMAN_x1r5g5b5,
35    PIXMAN_a1b5g5r5,
36    PIXMAN_x1b5g5r5,
37    PIXMAN_a4r4g4b4,
38    PIXMAN_x4r4g4b4,
39    PIXMAN_a4b4g4r4,
40    PIXMAN_x4b4g4r4,
41    PIXMAN_a8,
42    PIXMAN_r3g3b2,
43    PIXMAN_b2g3r3,
44    PIXMAN_a2r2g2b2,
45    PIXMAN_a2b2g2r2,
46    PIXMAN_c8,
47    PIXMAN_g8,
48    PIXMAN_x4c4,
49    PIXMAN_x4g4,
50    PIXMAN_c4,
51    PIXMAN_g4,
52    PIXMAN_g1,
53    PIXMAN_x4a4,
54    PIXMAN_a4,
55    PIXMAN_r1g2b1,
56    PIXMAN_b1g2r1,
57    PIXMAN_a1r1g1b1,
58    PIXMAN_a1b1g1r1,
59    PIXMAN_a1
60};
61
62static pixman_filter_t filters[] =
63{
64    PIXMAN_FILTER_NEAREST,
65    PIXMAN_FILTER_BILINEAR,
66    PIXMAN_FILTER_FAST,
67    PIXMAN_FILTER_GOOD,
68    PIXMAN_FILTER_BEST,
69    PIXMAN_FILTER_CONVOLUTION
70};
71
72static int
73get_size (void)
74{
75    switch (lcg_rand_n (28))
76    {
77    case 0:
78	return 1;
79
80    case 1:
81	return 2;
82
83    default:
84    case 2:
85	return lcg_rand_n (200);
86
87    case 4:
88	return lcg_rand_n (2000) + 1000;
89
90    case 5:
91	return 65535;
92
93    case 6:
94	return 65536;
95
96    case 7:
97	return lcg_rand_N (64000) + 63000;
98    }
99}
100
101static void
102destroy (pixman_image_t *image, void *data)
103{
104    if (image->type == BITS && image->bits.free_me != image->bits.bits)
105    {
106	uint32_t *bits;
107
108	if (image->bits.bits != (void *)0x01)
109	{
110	    bits = image->bits.bits;
111
112	    if (image->bits.rowstride < 0)
113		bits -= (- image->bits.rowstride * (image->bits.height - 1));
114
115	    fence_free (bits);
116	}
117    }
118
119    free (data);
120}
121
122static uint32_t
123real_reader (const void *src, int size)
124{
125    switch (size)
126    {
127    case 1:
128	return *(uint8_t *)src;
129    case 2:
130	return *(uint16_t *)src;
131    case 4:
132	return *(uint32_t *)src;
133    default:
134	assert (0);
135	return 0; /* silence MSVC */
136    }
137}
138
139static void
140real_writer (void *src, uint32_t value, int size)
141{
142    switch (size)
143    {
144    case 1:
145	*(uint8_t *)src = value;
146	break;
147
148    case 2:
149	*(uint16_t *)src = value;
150	break;
151
152    case 4:
153	*(uint32_t *)src = value;
154	break;
155
156    default:
157	assert (0);
158	break;
159    }
160}
161
162static uint32_t
163fake_reader (const void *src, int size)
164{
165    uint32_t r = lcg_rand_u32 ();
166
167    assert (size == 1 || size == 2 || size == 4);
168    return r & ((1 << (size * 8)) - 1);
169}
170
171static void
172fake_writer (void *src, uint32_t value, int size)
173{
174    assert (size == 1 || size == 2 || size == 4);
175}
176
177static int32_t
178log_rand (void)
179{
180    uint32_t mask;
181
182    mask = (1 << lcg_rand_n (31)) - 1;
183
184    return (lcg_rand () & mask) - (mask >> 1);
185}
186
187static pixman_image_t *
188create_random_bits_image (void)
189{
190    pixman_format_code_t format;
191    pixman_indexed_t *indexed;
192    pixman_image_t *image;
193    int width, height, stride;
194    uint32_t *bits;
195    pixman_read_memory_func_t read_func = NULL;
196    pixman_write_memory_func_t write_func = NULL;
197    pixman_filter_t filter;
198    pixman_fixed_t *coefficients = NULL;
199    int n_coefficients = 0;
200
201    /* format */
202    format = image_formats[lcg_rand_n (ARRAY_LENGTH (image_formats))];
203
204    indexed = NULL;
205    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
206    {
207	indexed = malloc (sizeof (pixman_indexed_t));
208
209	initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), TRUE);
210    }
211    else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
212    {
213	indexed = malloc (sizeof (pixman_indexed_t));
214
215	initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), FALSE);
216    }
217    else
218    {
219	indexed = NULL;
220    }
221
222    /* size */
223    width = get_size ();
224    height = get_size ();
225
226    if ((uint64_t)width * height > 200000)
227    {
228	if (lcg_rand_n(2) == 0)
229	    height = 200000 / width;
230	else
231	    width = 200000 / height;
232    }
233
234    if (height == 0)
235	height = 1;
236    if (width == 0)
237	width = 1;
238
239    /* bits */
240    switch (lcg_rand_n (7))
241    {
242    default:
243    case 0:
244	stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
245	stride = (stride + 3) & (~3);
246	bits = (uint32_t *)make_random_bytes (height * stride);
247	break;
248
249    case 1:
250	stride = 0;
251	bits = NULL;
252	break;
253
254    case 2: /* Zero-filled */
255	stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
256	stride = (stride + 3) & (~3);
257	bits = fence_malloc (height * stride);
258	if (!bits)
259	    return NULL;
260	memset (bits, 0, height * stride);
261	break;
262
263    case 3: /* Filled with 0xFF */
264	stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
265	stride = (stride + 3) & (~3);
266	bits = fence_malloc (height * stride);
267	if (!bits)
268	    return NULL;
269	memset (bits, 0xff, height * stride);
270	break;
271
272    case 4: /* bits is a bad pointer, has read/write functions */
273	stride = 232;
274	bits = (void *)0x01;
275	read_func = fake_reader;
276	write_func = fake_writer;
277	break;
278
279    case 5: /* bits is a real pointer, has read/write functions */
280	stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17);
281	stride = (stride + 3) & (~3);
282	bits = fence_malloc (height * stride);
283	if (!bits)
284	    return NULL;
285	memset (bits, 0xff, height * stride);
286	read_func = real_reader;
287	write_func = real_writer;
288	break;
289
290    case 6: /* bits is a real pointer, stride is negative */
291	stride = (width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17));
292	stride = (stride + 3) & (~3);
293	bits = (uint32_t *)make_random_bytes (height * stride);
294	if (!bits)
295	    return NULL;
296	bits += ((height - 1) * stride) / 4;
297	stride = - stride;
298	break;
299    }
300
301    /* Filter */
302    filter = filters[lcg_rand_n (ARRAY_LENGTH (filters))];
303    if (filter == PIXMAN_FILTER_CONVOLUTION)
304    {
305	int width = lcg_rand_n (17);
306	int height = lcg_rand_n (19);
307
308	n_coefficients = width * height + 2;
309	coefficients = malloc (n_coefficients * sizeof (pixman_fixed_t));
310
311	if (coefficients)
312	{
313	    int i;
314
315	    for (i = 0; i < width * height; ++i)
316		coefficients[i + 2] = lcg_rand_u32();
317
318	    coefficients[0] = width << 16;
319	    coefficients[1] = height << 16;
320	}
321	else
322	{
323	    filter = PIXMAN_FILTER_BEST;
324	}
325    }
326
327    /* Finally create the image */
328    image = pixman_image_create_bits (format, width, height, bits, stride);
329    if (!image)
330	return NULL;
331
332    pixman_image_set_indexed (image, indexed);
333    pixman_image_set_destroy_function (image, destroy, indexed);
334    pixman_image_set_accessors (image, read_func, write_func);
335    pixman_image_set_filter (image, filter, coefficients, n_coefficients);
336
337    return image;
338}
339
340static pixman_repeat_t repeats[] =
341{
342    PIXMAN_REPEAT_NONE,
343    PIXMAN_REPEAT_NORMAL,
344    PIXMAN_REPEAT_REFLECT,
345    PIXMAN_REPEAT_PAD
346};
347
348static uint32_t
349absolute (int32_t i)
350{
351    return i < 0? -i : i;
352}
353
354static void
355set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
356{
357    pixman_repeat_t repeat;
358
359    /* Set properties that are generic to all images */
360
361    /* Repeat */
362    repeat = repeats[lcg_rand_n (ARRAY_LENGTH (repeats))];
363    pixman_image_set_repeat (image, repeat);
364
365    /* Alpha map */
366    if (allow_alpha_map && lcg_rand_n (3) == 0)
367    {
368	pixman_image_t *alpha_map;
369	int16_t x, y;
370
371	alpha_map = create_random_bits_image ();
372
373	if (alpha_map)
374	{
375	    set_general_properties (alpha_map, FALSE);
376
377	    x = lcg_rand_N (100000) - 65536;
378	    y = lcg_rand_N (100000) - 65536;
379
380	    pixman_image_set_alpha_map (image, alpha_map, x, y);
381
382	    pixman_image_unref (alpha_map);
383	}
384    }
385
386    /* Component alpha */
387    pixman_image_set_component_alpha (image, lcg_rand_n (3) == 0);
388
389    /* Clip region */
390    if (lcg_rand_n (8) != 0)
391    {
392	pixman_region32_t region;
393	int i, n_rects;
394
395	pixman_region32_init (&region);
396
397	switch (lcg_rand_n (10))
398	{
399	case 0:
400	    n_rects = 0;
401	    break;
402
403	case 1: case 2: case 3:
404	    n_rects = 1;
405	    break;
406
407	case 4: case 5:
408	    n_rects = 2;
409	    break;
410
411	case 6: case 7:
412	    n_rects = 3;
413
414	default:
415	    n_rects = lcg_rand_n (100);
416	    break;
417	}
418
419	for (i = 0; i < n_rects; ++i)
420	{
421	    uint32_t width, height;
422	    int x, y;
423
424	    x = log_rand();
425	    y = log_rand();
426	    width = absolute (log_rand ()) + 1;
427	    height = absolute (log_rand ()) + 1;
428
429	    pixman_region32_union_rect (
430		&region, &region, x, y, width, height);
431	}
432
433	pixman_image_set_clip_region32 (image, &region);
434
435	pixman_region32_fini (&region);
436    }
437
438    /* Whether source clipping is enabled */
439    pixman_image_set_source_clipping (image, !!lcg_rand_n (2));
440
441    /* Client clip */
442    pixman_image_set_has_client_clip (image, !!lcg_rand_n (2));
443
444    /* Transform */
445    if (lcg_rand_n (5) < 2)
446    {
447	pixman_transform_t xform;
448	int i, j, k;
449	uint32_t tx, ty, sx, sy;
450	uint32_t c, s;
451
452	memset (&xform, 0, sizeof xform);
453	xform.matrix[0][0] = pixman_fixed_1;
454	xform.matrix[1][1] = pixman_fixed_1;
455	xform.matrix[2][2] = pixman_fixed_1;
456
457	for (k = 0; k < 3; ++k)
458	{
459	    switch (lcg_rand_n (4))
460	    {
461	    case 0:
462		/* rotation */
463		c = lcg_rand_N (2 * 65536) - 65536;
464		s = lcg_rand_N (2 * 65536) - 65536;
465		pixman_transform_rotate (&xform, NULL, c, s);
466		break;
467
468	    case 1:
469		/* translation */
470		tx = lcg_rand_u32();
471		ty = lcg_rand_u32();
472		pixman_transform_translate (&xform, NULL, tx, ty);
473		break;
474
475	    case 2:
476		/* scale */
477		sx = lcg_rand_u32();
478		sy = lcg_rand_u32();
479		pixman_transform_scale (&xform, NULL, sx, sy);
480		break;
481
482	    case 3:
483		if (lcg_rand_n (16) == 0)
484		{
485		    /* random */
486		    for (i = 0; i < 3; ++i)
487			for (j = 0; j < 3; ++j)
488			    xform.matrix[i][j] = lcg_rand_u32();
489		    break;
490		}
491		else if (lcg_rand_n (16) == 0)
492		{
493		    /* zero */
494		    memset (&xform, 0, sizeof xform);
495		}
496		break;
497	    }
498	}
499
500	pixman_image_set_transform (image, &xform);
501    }
502}
503
504static pixman_color_t
505random_color (void)
506{
507    pixman_color_t color =
508    {
509	lcg_rand() & 0xffff,
510	lcg_rand() & 0xffff,
511	lcg_rand() & 0xffff,
512	lcg_rand() & 0xffff,
513    };
514
515    return color;
516}
517
518
519static pixman_image_t *
520create_random_solid_image (void)
521{
522    pixman_color_t color = random_color();
523    pixman_image_t *image = pixman_image_create_solid_fill (&color);
524
525    return image;
526}
527
528static pixman_gradient_stop_t *
529create_random_stops (int *n_stops)
530{
531    pixman_fixed_t step;
532    pixman_fixed_t s;
533    int i;
534    pixman_gradient_stop_t *stops;
535
536    *n_stops = lcg_rand_n (50) + 1;
537
538    step = pixman_fixed_1 / *n_stops;
539
540    stops = malloc (*n_stops * sizeof (pixman_gradient_stop_t));
541
542    s = 0;
543    for (i = 0; i < (*n_stops) - 1; ++i)
544    {
545	stops[i].x = s;
546	stops[i].color = random_color();
547
548	s += step;
549    }
550
551    stops[*n_stops - 1].x = pixman_fixed_1;
552    stops[*n_stops - 1].color = random_color();
553
554    return stops;
555}
556
557static pixman_point_fixed_t
558create_random_point (void)
559{
560    pixman_point_fixed_t p;
561
562    p.x = log_rand ();
563    p.y = log_rand ();
564
565    return p;
566}
567
568static pixman_image_t *
569create_random_linear_image (void)
570{
571    int n_stops;
572    pixman_gradient_stop_t *stops;
573    pixman_point_fixed_t p1, p2;
574    pixman_image_t *result;
575
576    stops = create_random_stops (&n_stops);
577    if (!stops)
578	return NULL;
579
580    p1 = create_random_point ();
581    p2 = create_random_point ();
582
583    result = pixman_image_create_linear_gradient (&p1, &p2, stops, n_stops);
584
585    free (stops);
586
587    return result;
588}
589
590static pixman_image_t *
591create_random_radial_image (void)
592{
593    int n_stops;
594    pixman_gradient_stop_t *stops;
595    pixman_point_fixed_t inner_c, outer_c;
596    pixman_fixed_t inner_r, outer_r;
597    pixman_image_t *result;
598
599    inner_c = create_random_point();
600    outer_c = create_random_point();
601    inner_r = lcg_rand();
602    outer_r = lcg_rand();
603
604    stops = create_random_stops (&n_stops);
605
606    if (!stops)
607	return NULL;
608
609    result = pixman_image_create_radial_gradient (
610	&inner_c, &outer_c, inner_r, outer_r, stops, n_stops);
611
612    free (stops);
613
614    return result;
615}
616
617static pixman_image_t *
618create_random_conical_image (void)
619{
620    pixman_gradient_stop_t *stops;
621    int n_stops;
622    pixman_point_fixed_t c;
623    pixman_fixed_t angle;
624    pixman_image_t *result;
625
626    c = create_random_point();
627    angle = lcg_rand();
628
629    stops = create_random_stops (&n_stops);
630
631    if (!stops)
632	return NULL;
633
634    result = pixman_image_create_conical_gradient (&c, angle, stops, n_stops);
635
636    free (stops);
637
638    return result;
639}
640
641static pixman_image_t *
642create_random_image (void)
643{
644    pixman_image_t *result;
645
646    switch (lcg_rand_n (5))
647    {
648    default:
649    case 0:
650	result = create_random_bits_image ();
651	break;
652
653    case 1:
654	result = create_random_solid_image ();
655	break;
656
657    case 2:
658	result = create_random_linear_image ();
659	break;
660
661    case 3:
662	result = create_random_radial_image ();
663	break;
664
665    case 4:
666	result = create_random_conical_image ();
667	break;
668    }
669
670    if (result)
671	set_general_properties (result, TRUE);
672
673    return result;
674}
675
676static const pixman_op_t op_list[] =
677{
678    PIXMAN_OP_SRC,
679    PIXMAN_OP_OVER,
680    PIXMAN_OP_ADD,
681    PIXMAN_OP_CLEAR,
682    PIXMAN_OP_SRC,
683    PIXMAN_OP_DST,
684    PIXMAN_OP_OVER,
685    PIXMAN_OP_OVER_REVERSE,
686    PIXMAN_OP_IN,
687    PIXMAN_OP_IN_REVERSE,
688    PIXMAN_OP_OUT,
689    PIXMAN_OP_OUT_REVERSE,
690    PIXMAN_OP_ATOP,
691    PIXMAN_OP_ATOP_REVERSE,
692    PIXMAN_OP_XOR,
693    PIXMAN_OP_ADD,
694    PIXMAN_OP_SATURATE,
695    PIXMAN_OP_DISJOINT_CLEAR,
696    PIXMAN_OP_DISJOINT_SRC,
697    PIXMAN_OP_DISJOINT_DST,
698    PIXMAN_OP_DISJOINT_OVER,
699    PIXMAN_OP_DISJOINT_OVER_REVERSE,
700    PIXMAN_OP_DISJOINT_IN,
701    PIXMAN_OP_DISJOINT_IN_REVERSE,
702    PIXMAN_OP_DISJOINT_OUT,
703    PIXMAN_OP_DISJOINT_OUT_REVERSE,
704    PIXMAN_OP_DISJOINT_ATOP,
705    PIXMAN_OP_DISJOINT_ATOP_REVERSE,
706    PIXMAN_OP_DISJOINT_XOR,
707    PIXMAN_OP_CONJOINT_CLEAR,
708    PIXMAN_OP_CONJOINT_SRC,
709    PIXMAN_OP_CONJOINT_DST,
710    PIXMAN_OP_CONJOINT_OVER,
711    PIXMAN_OP_CONJOINT_OVER_REVERSE,
712    PIXMAN_OP_CONJOINT_IN,
713    PIXMAN_OP_CONJOINT_IN_REVERSE,
714    PIXMAN_OP_CONJOINT_OUT,
715    PIXMAN_OP_CONJOINT_OUT_REVERSE,
716    PIXMAN_OP_CONJOINT_ATOP,
717    PIXMAN_OP_CONJOINT_ATOP_REVERSE,
718    PIXMAN_OP_CONJOINT_XOR,
719    PIXMAN_OP_MULTIPLY,
720    PIXMAN_OP_SCREEN,
721    PIXMAN_OP_OVERLAY,
722    PIXMAN_OP_DARKEN,
723    PIXMAN_OP_LIGHTEN,
724    PIXMAN_OP_COLOR_DODGE,
725    PIXMAN_OP_COLOR_BURN,
726    PIXMAN_OP_HARD_LIGHT,
727    PIXMAN_OP_DIFFERENCE,
728    PIXMAN_OP_EXCLUSION,
729    PIXMAN_OP_SOFT_LIGHT,
730    PIXMAN_OP_HSL_HUE,
731    PIXMAN_OP_HSL_SATURATION,
732    PIXMAN_OP_HSL_COLOR,
733    PIXMAN_OP_HSL_LUMINOSITY,
734};
735
736static void
737run_test (uint32_t seed, pixman_bool_t verbose, uint32_t mod)
738{
739    pixman_image_t *source, *mask, *dest;
740    pixman_op_t op;
741
742    if (verbose)
743    {
744	if (mod == 0 || (seed % mod) == 0)
745	    printf ("Seed 0x%08x\n", seed);
746    }
747
748    lcg_srand (seed);
749
750    source = create_random_image ();
751    mask   = create_random_image ();
752    dest   = create_random_bits_image ();
753
754    if (source && mask && dest)
755    {
756	set_general_properties (dest, TRUE);
757
758	op = op_list [lcg_rand_n (ARRAY_LENGTH (op_list))];
759
760	pixman_image_composite32 (op,
761				  source, mask, dest,
762				  log_rand(), log_rand(),
763				  log_rand(), log_rand(),
764				  log_rand(), log_rand(),
765				  absolute (log_rand()),
766				  absolute (log_rand()));
767    }
768    if (source)
769	pixman_image_unref (source);
770    if (mask)
771	pixman_image_unref (mask);
772    if (dest)
773	pixman_image_unref (dest);
774}
775
776static pixman_bool_t
777get_int (char *s, uint32_t *i)
778{
779    char *end;
780    int p;
781
782    p = strtol (s, &end, 0);
783
784    if (end != s && *end == 0)
785    {
786	*i = p;
787	return TRUE;
788    }
789
790    return FALSE;
791}
792
793int
794main (int argc, char **argv)
795{
796    int verbose = FALSE;
797    uint32_t seed = 1;
798    uint32_t n_tests = 0xffffffff;
799    uint32_t mod = 0;
800    pixman_bool_t use_threads = TRUE;
801    uint32_t i;
802
803    pixman_disable_out_of_bounds_workaround ();
804
805    enable_fp_exceptions();
806
807    if (getenv ("VERBOSE") != NULL)
808	verbose = TRUE;
809
810    for (i = 1; i < argc; ++i)
811    {
812	if (strcmp (argv[i], "-v") == 0)
813	{
814	    verbose = TRUE;
815
816	    if (i + 1 < argc)
817	    {
818		get_int (argv[i + 1], &mod);
819		i++;
820	    }
821	}
822	else if (strcmp (argv[i], "-s") == 0 && i + 1 < argc)
823	{
824	    get_int (argv[i + 1], &seed);
825	    use_threads = FALSE;
826	    i++;
827	}
828	else if (strcmp (argv[i], "-n") == 0 && i + 1 < argc)
829	{
830	    get_int (argv[i + 1], &n_tests);
831	    i++;
832	}
833	else
834	{
835	    if (strcmp (argv[i], "-h") != 0)
836		printf ("Unknown option '%s'\n\n", argv[i]);
837
838	    printf ("Options:\n\n"
839		    "-n <number>        Number of tests to run\n"
840		    "-s <seed> 	        Seed of first test (ignored if PIXMAN_RANDOMIZE_TESTS is set)\n"
841		    "-v                 Print out seeds\n"
842		    "-v <n>             Print out every n'th seed\n\n");
843
844	    exit (-1);
845	}
846    }
847
848    if (n_tests == 0xffffffff)
849	n_tests = 8000;
850
851    if (getenv ("PIXMAN_RANDOMIZE_TESTS"))
852    {
853	seed = get_random_seed();
854	printf ("First seed: 0x%08x\n", seed);
855    }
856
857    if (use_threads)
858    {
859#ifdef USE_OPENMP
860#   pragma omp parallel for default(none) shared(verbose, n_tests, mod, seed)
861#endif
862	for (i = seed; i < seed + n_tests; ++i)
863	    run_test (i, verbose, mod);
864    }
865    else
866    {
867	for (i = seed; i < seed + n_tests; ++i)
868	    run_test (i, verbose, mod);
869    }
870
871    return 0;
872}
873