Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
comment tests we don't support in MPI3, and fix a few we support
[simgrid.git] / teshsuite / smpi / mpich3-test / datatype / indexed-misc.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2001 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 #include "mpi.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "mpitestconf.h"
10 #ifdef HAVE_STRING_H
11 #include <string.h>
12 #endif
13 #include <assert.h>
14 #include <limits.h>
15
16 static int verbose = 1;
17
18 #define check(cond_)                                                                             \
19     do {                                                                                         \
20         if (!(cond_)) {                                                                          \
21             if (verbose) {                                                                       \
22                 fprintf(stderr, "condition '%s' does not hold, at line %d\n", #cond_, __LINE__); \
23             }                                                                                    \
24             errs += 1;                                                                           \
25         }                                                                                        \
26     } while (0)
27
28 #define check_err(err_, what_failed_)                                                 \
29     do {                                                                              \
30         if (err_) {                                                                   \
31             if (verbose) {                                                            \
32                 fprintf(stderr, "error: %s, at line %d\n", (what_failed_), __LINE__); \
33             }                                                                         \
34             errs += (err_);                                                           \
35         }                                                                             \
36     } while (0)
37
38 /* tests */
39 int indexed_contig_test(void);
40 int indexed_zeroblock_first_test(void);
41 int indexed_zeroblock_middle_test(void);
42 int indexed_zeroblock_last_test(void);
43 int indexed_contig_leading_zero_test(void);
44 int indexed_same_lengths(void);
45
46 /* helper functions */
47 int parse_args(int argc, char **argv);
48 static int pack_and_unpack(char *typebuf, int count, MPI_Datatype datatype, int typebufsz);
49
50 int main(int argc, char **argv)
51 {
52     int err, errs = 0;
53
54     MPI_Init(&argc, &argv);     /* MPI-1.2 doesn't allow for MPI_Init(0,0) */
55     parse_args(argc, argv);
56
57     /* To improve reporting of problems about operations, we
58      * change the error handler to errors return */
59     MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
60
61     /* perform some tests */
62     err = indexed_contig_test();
63     if (err && verbose)
64         fprintf(stderr, "%d errors in indexed_contig_test.\n", err);
65     errs += err;
66
67     err = indexed_zeroblock_first_test();
68     if (err && verbose)
69         fprintf(stderr, "%d errors in indexed_zeroblock_first_test.\n", err);
70     errs += err;
71
72     err = indexed_zeroblock_middle_test();
73     if (err && verbose)
74         fprintf(stderr, "%d errors in indexed_zeroblock_middle_test.\n", err);
75     errs += err;
76
77     err = indexed_zeroblock_last_test();
78     if (err && verbose)
79         fprintf(stderr, "%d errors in indexed_zeroblock_last_test.\n", err);
80     errs += err;
81
82     err = indexed_contig_leading_zero_test();
83     if (err && verbose)
84         fprintf(stderr, "%d errors in indexed_contig_leading_zero_test.\n", err);
85     errs += err;
86
87     err = indexed_same_lengths();
88     if (err && verbose)
89         fprintf(stderr, "%d errors in indexed_contig_leading_zero_test.\n", err);
90     errs += err;
91
92     /* print message and exit */
93     if (errs) {
94         fprintf(stderr, "Found %d errors\n", errs);
95     }
96     else {
97         printf(" No Errors\n");
98     }
99     MPI_Finalize();
100     return 0;
101 }
102
103 int indexed_zeroblock_first_test(void)
104 {
105     int err, errs = 0;
106
107     MPI_Datatype type;
108     int len[3] = { 0, 1, 1 };
109     int disp[3] = { 0, 1, 4 };
110     MPI_Aint lb, ub;
111
112     err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
113     if (err != MPI_SUCCESS) {
114         if (verbose) {
115             fprintf(stderr, "error creating indexed type in indexed_zeroblock_first_test()\n");
116         }
117         errs += 1;
118     }
119
120     MPI_Type_lb(type, &lb);
121     if (lb != sizeof(int)) {
122         if (verbose) {
123             fprintf(stderr, "lb mismatch; is %d, should be %d\n", (int) lb, (int) sizeof(int));
124         }
125         errs++;
126     }
127     MPI_Type_ub(type, &ub);
128     if (ub != 5 * sizeof(int)) {
129         if (verbose) {
130             fprintf(stderr,
131                     "ub mismatch; is %d, should be %d\n", (int) ub, (int) (5 * sizeof(int)));
132         }
133         errs++;
134     }
135
136     MPI_Type_free(&type);
137
138     return errs;
139 }
140
141 int indexed_zeroblock_middle_test(void)
142 {
143     int err, errs = 0;
144
145     MPI_Datatype type;
146     int len[3] = { 1, 0, 1 };
147     int disp[3] = { 1, 2, 4 };
148     MPI_Aint lb, ub;
149
150     err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
151     if (err != MPI_SUCCESS) {
152         if (verbose) {
153             fprintf(stderr, "error creating indexed type in indexed_zeroblock_middle_test()\n");
154         }
155         errs += 1;
156     }
157
158     MPI_Type_lb(type, &lb);
159     if (lb != sizeof(int)) {
160         if (verbose) {
161             fprintf(stderr, "lb mismatch; is %d, should be %d\n", (int) lb, (int) sizeof(int));
162         }
163         errs++;
164     }
165     MPI_Type_ub(type, &ub);
166     if (ub != 5 * sizeof(int)) {
167         if (verbose) {
168             fprintf(stderr,
169                     "ub mismatch; is %d, should be %d\n", (int) ub, (int) (5 * sizeof(int)));
170         }
171         errs++;
172     }
173
174     MPI_Type_free(&type);
175
176     return errs;
177 }
178
179 int indexed_zeroblock_last_test(void)
180 {
181     int err, errs = 0;
182
183     MPI_Datatype type;
184     int len[3] = { 1, 1, 0 };
185     int disp[3] = { 1, 4, 8 };
186     MPI_Aint lb, ub;
187
188     err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
189     if (err != MPI_SUCCESS) {
190         if (verbose) {
191             fprintf(stderr, "error creating indexed type in indexed_zeroblock_last_test()\n");
192         }
193         errs += 1;
194     }
195
196     MPI_Type_lb(type, &lb);
197     if (lb != sizeof(int)) {
198         if (verbose) {
199             fprintf(stderr, "lb mismatch; is %d, should be %d\n", (int) lb, (int) sizeof(int));
200         }
201         errs++;
202     }
203     MPI_Type_ub(type, &ub);
204     if (ub != 5 * sizeof(int)) {
205         if (verbose) {
206             fprintf(stderr,
207                     "ub mismatch; is %d, should be %d\n", (int) ub, (int) (5 * sizeof(int)));
208         }
209         errs++;
210     }
211
212     MPI_Type_free(&type);
213
214     return errs;
215 }
216
217 /* indexed_contig_test()
218  *
219  * Tests behavior with an indexed array that can be compacted but should
220  * continue to be stored as an indexed type.  Specifically for coverage.
221  *
222  * Returns the number of errors encountered.
223  */
224 int indexed_contig_test(void)
225 {
226     int buf[9] = { -1, 1, 2, 3, -2, 4, 5, -3, 6 };
227     int err, errs = 0;
228
229     int i, count = 5;
230     int blklen[] = { 1, 2, 1, 1, 1 };
231     int disp[] = { 1, 2, 5, 6, 8 };
232     MPI_Datatype newtype;
233
234     int size, int_size;
235
236     err = MPI_Type_indexed(count, blklen, disp, MPI_INT, &newtype);
237     if (err != MPI_SUCCESS) {
238         if (verbose) {
239             fprintf(stderr, "error creating indexed type in indexed_contig_test()\n");
240         }
241         errs++;
242     }
243
244     MPI_Type_size(MPI_INT, &int_size);
245
246     err = MPI_Type_size(newtype, &size);
247     if (err != MPI_SUCCESS) {
248         if (verbose) {
249             fprintf(stderr, "error obtaining type size in indexed_contig_test()\n");
250         }
251         errs++;
252     }
253
254     if (size != 6 * int_size) {
255         if (verbose) {
256             fprintf(stderr, "error: size != 6 * int_size in indexed_contig_test()\n");
257         }
258         errs++;
259     }
260
261     MPI_Type_commit(&newtype);
262
263     err = pack_and_unpack((char *) buf, 1, newtype, 9 * sizeof(int));
264     if (err != 0) {
265         if (verbose) {
266             fprintf(stderr, "error packing/unpacking in indexed_contig_test()\n");
267         }
268         errs += err;
269     }
270
271     for (i = 0; i < 9; i++) {
272         int goodval;
273
274         switch (i) {
275         case 1:
276             goodval = 1;
277             break;
278         case 2:
279             goodval = 2;
280             break;
281         case 3:
282             goodval = 3;
283             break;
284         case 5:
285             goodval = 4;
286             break;
287         case 6:
288             goodval = 5;
289             break;
290         case 8:
291             goodval = 6;
292             break;
293         default:
294             goodval = 0;        /* pack_and_unpack() zeros before unpack */
295             break;
296         }
297         if (buf[i] != goodval) {
298             errs++;
299             if (verbose)
300                 fprintf(stderr, "buf[%d] = %d; should be %d\n", i, buf[i], goodval);
301         }
302     }
303
304     MPI_Type_free(&newtype);
305
306     return errs;
307 }
308
309 /* very similar to indexed_zeroblock_first_test, but only has a single contig in
310  * order to catch a particular optimization path in MPICH's
311  * Dataloop_create_indexed routine */
312 int indexed_contig_leading_zero_test(void)
313 {
314     int err, errs = 0;
315
316     int i;
317     MPI_Datatype type = MPI_DATATYPE_NULL;
318     MPI_Datatype struct_type = MPI_DATATYPE_NULL;
319     MPI_Datatype types[2];
320     int len[3] = { 0, 4, 0 };
321     int disp[3] = { INT_MAX, 2, INT_MAX };
322     MPI_Aint adisp[3];
323     MPI_Aint lb, ub;
324     int *buf = NULL;
325
326     err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
327     check_err(err, "creating indexed type in indexed_contig_leading_zero_test()");
328     err = MPI_Type_commit(&type);
329     check_err(err, "committing indexed type in indexed_contig_leading_zero_test()");
330
331     MPI_Type_lb(type, &lb);
332     check(lb == 2 * sizeof(int));
333     MPI_Type_ub(type, &ub);
334     check(ub == 6 * sizeof(int));
335
336     /* make sure packing/unpacking works (hits a simple "is_contig" case in
337      * MPICH's pack/unpack routines) */
338     buf = malloc(10 * sizeof(int));
339     assert(buf != NULL);
340     for (i = 0; i < 10; ++i) {
341         buf[i] = i + 1;
342     }
343     err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
344     check_err(err, "packing/unpacking in indexed_contig_leading_zero_test()");
345     for (i = 0; i < 10; ++i) {
346         int expected;
347         if (i >= 2 && i < 6)
348             expected = i + 1;
349         else
350             expected = 0;
351         check(buf[i] == expected);
352     }
353     free(buf);
354
355     /* -------------------------------------------------------------------- */
356     /* A more rigorous test of the indexed type.  Use a hard-to-optimize struct
357      * type to force a more complicated datatype processing path
358      * (MPID_Segment_manipulate in MPICH) */
359     len[0] = 1;
360     len[1] = 1;
361     adisp[0] = 0;
362     adisp[1] = 8 * sizeof(int);
363     types[0] = type;
364     types[1] = MPI_INT;
365
366     /* struct layout: xx0123xx4x ('x' indicates a hole), one char is an
367      * MPI_INT */
368     MPI_Type_create_struct(2, len, adisp, types, &struct_type);
369     check_err(err, "creating struct type in indexed_contig_leading_zero_test()");
370     err = MPI_Type_commit(&struct_type);
371     check_err(err, "committing struct type in indexed_contig_leading_zero_test()");
372
373     buf = malloc(10 * sizeof(int));
374     assert(buf != NULL);
375     for (i = 0; i < 10; ++i) {
376         buf[i] = i + 1;
377     }
378     err = pack_and_unpack((char *) buf, 1, struct_type, 10 * sizeof(int));
379     check_err(err, "packing/unpacking in indexed_contig_test()");
380
381     for (i = 0; i < 10; ++i) {
382         int expected;
383         if ((i >= 2 && i < 6) || i == 8)
384             expected = i + 1;
385         else
386             expected = 0;
387         check(buf[i] == expected);
388     }
389     free(buf);
390
391     MPI_Type_free(&struct_type);
392     MPI_Type_free(&type);
393
394     /* -------------------------------------------------------------------- */
395     /* now do the same as above, but with hindexed */
396     len[0] = 0;
397     len[1] = 4;
398     len[2] = 0;
399     /* use *_MAX vars to improve our chances of hitting any pointer-casting
400      * bugs in a big way (segfaults, etc.) */
401     /* FIXME: This should also look at long, or use a different approach */
402 #if defined(HAVE_LONG_LONG) && defined(LLONG_MAX)
403     if (sizeof(MPI_Aint) == sizeof(long long)) {
404         adisp[0] = (MPI_Aint) LLONG_MAX;
405         adisp[1] = 2 * sizeof(int);
406         adisp[2] = (MPI_Aint) LLONG_MAX;
407     }
408     else
409 #endif
410     {
411         adisp[0] = (MPI_Aint) INT_MAX;
412         adisp[1] = 2 * sizeof(int);
413         adisp[2] = (MPI_Aint) INT_MAX;
414     }
415
416     err = MPI_Type_hindexed(3, len, adisp, MPI_INT, &type);
417     check_err(err, "creating hindexed type in indexed_contig_leading_zero_test()");
418
419     err = MPI_Type_commit(&type);
420     check_err(err, "committing hindexed type in indexed_contig_leading_zero_test()");
421
422     MPI_Type_lb(type, &lb);
423     check(lb == 2 * sizeof(int));
424     MPI_Type_ub(type, &ub);
425     check(ub == 6 * sizeof(int));
426
427     buf = malloc(10 * sizeof(int));
428     assert(buf != NULL);
429     for (i = 0; i < 10; ++i) {
430         buf[i] = i + 1;
431     }
432     err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
433     check_err(err, "packing/unpacking in indexed_contig_test()");
434
435     for (i = 0; i < 10; ++i) {
436         int expected;
437         if (i >= 2 && i < 6)
438             expected = i + 1;
439         else
440             expected = 0;
441         check(buf[i] == expected);
442     }
443     free(buf);
444
445
446     /* -------------------------------------------------------------------- */
447     /* A more rigorous test of the hindexed type.  Use a hard-to-optimize struct
448      * type to force a more complicated datatype processing path
449      * (MPID_Segment_manipulate in MPICH) */
450     len[0] = 1;
451     len[1] = 1;
452     adisp[0] = 0;
453     adisp[1] = 8 * sizeof(int);
454
455     /* struct layout: xx0123xx4x ('x' indicates a hole), one char is an
456      * MPI_INT */
457     err = MPI_Type_create_struct(2, len, adisp, types, &struct_type);
458     check_err(err, "committing struct type in indexed_contig_leading_zero_test()");
459     err = MPI_Type_commit(&struct_type);
460     check_err(err, "committing struct type in indexed_contig_leading_zero_test()");
461
462     buf = malloc(10 * sizeof(int));
463     assert(buf != NULL);
464     for (i = 0; i < 10; ++i) {
465         buf[i] = i + 1;
466     }
467     /* fails in old MPICH (3.0rc1 and earlier), despite correct ub/lb
468      * determination */
469     err = pack_and_unpack((char *) buf, 1, struct_type, 10 * sizeof(int));
470     check_err(err, "packing/unpacking in indexed_contig_test()");
471
472     for (i = 0; i < 10; ++i) {
473         int expected;
474         if ((i >= 2 && i < 6) || i == 8)
475             expected = i + 1;
476         else
477             expected = 0;
478         check(buf[i] == expected);
479     }
480     free(buf);
481
482     MPI_Type_free(&struct_type);
483     MPI_Type_free(&type);
484
485     return errs;
486 }
487
488 /* Test an indexed (and hindexed) type where the block length is the same for
489  * all blocks, but with differing displacements so that it cannot directly be
490  * converted to a vector type.  It is also important to add a dummy element at
491  * the beginning in order to cause int/MPI_Aint misalignment for the
492  * displacement of the first non-zero-width component. */
493 int indexed_same_lengths(void)
494 {
495     int err, errs = 0;
496
497     int i;
498     MPI_Datatype type = MPI_DATATYPE_NULL;
499     int len[4];
500     int disp[4];
501     MPI_Aint adisp[4];
502     MPI_Aint lb, ub;
503     int *buf = NULL;
504
505     len[0] = 0;
506     len[1] = 1;
507     len[2] = 1;
508     len[3] = 1;
509
510     disp[0] = 0;
511     disp[1] = 1;
512     disp[2] = 3;
513     disp[3] = 8;
514
515     err = MPI_Type_indexed(4, len, disp, MPI_INT, &type);
516     check_err(err, "creating indexed type in indexed_same_lengths()");
517     err = MPI_Type_commit(&type);
518     check_err(err, "committing indexed type in indexed_same_lengths()");
519
520     MPI_Type_lb(type, &lb);
521     check(lb == 1 * sizeof(int));
522     MPI_Type_ub(type, &ub);
523     check(ub == 9 * sizeof(int));
524
525     buf = malloc(10 * sizeof(int));
526     assert(buf != NULL);
527     for (i = 0; i < 10; ++i) {
528         buf[i] = i + 1;
529     }
530     err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
531     check_err(err, "packing/unpacking in indexed_same_lengths()");
532     for (i = 0; i < 10; ++i) {
533         int expected;
534         if (i == 1 || i == 3 || i == 8)
535             expected = i + 1;
536         else
537             expected = 0;
538         check(buf[i] == expected);
539     }
540     free(buf);
541
542     MPI_Type_free(&type);
543
544     /* -------------------------------------------------------------------- */
545     /* now do the same as above, but with hindexed */
546     len[0] = 0;
547     len[1] = 1;
548     len[2] = 1;
549     len[3] = 1;
550
551     adisp[0] = 0 * sizeof(int);
552     adisp[1] = 1 * sizeof(int);
553     adisp[2] = 3 * sizeof(int);
554     adisp[3] = 8 * sizeof(int);
555
556     err = MPI_Type_hindexed(4, len, adisp, MPI_INT, &type);
557     check_err(err, "creating hindexed type in indexed_same_lengths()");
558     err = MPI_Type_commit(&type);
559     check_err(err, "committing hindexed type in indexed_same_lengths()");
560
561     MPI_Type_lb(type, &lb);
562     check(lb == 1 * sizeof(int));
563     MPI_Type_ub(type, &ub);
564     check(ub == 9 * sizeof(int));
565
566     buf = malloc(10 * sizeof(int));
567     assert(buf != NULL);
568     for (i = 0; i < 10; ++i) {
569         buf[i] = i + 1;
570     }
571     err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
572     check_err(err, "packing/unpacking in indexed_same_lengths()");
573     for (i = 0; i < 10; ++i) {
574         int expected;
575         if (i == 1 || i == 3 || i == 8)
576             expected = i + 1;
577         else
578             expected = 0;
579         check(buf[i] == expected);
580     }
581     free(buf);
582
583     MPI_Type_free(&type);
584
585     return errs;
586 }
587
588 /* pack_and_unpack()
589  *
590  * Perform packing and unpacking of a buffer for the purposes of checking
591  * to see if we are processing a type correctly.  Zeros the buffer between
592  * these two operations, so the data described by the type should be in
593  * place upon return but all other regions of the buffer should be zero.
594  *
595  * Parameters:
596  * typebuf - pointer to buffer described by datatype and count that
597  *           will be packed and then unpacked into
598  * count, datatype - description of typebuf
599  * typebufsz - size of typebuf; used specifically to zero the buffer
600  *             between the pack and unpack steps
601  *
602  */
603 static int pack_and_unpack(char *typebuf, int count, MPI_Datatype datatype, int typebufsz)
604 {
605     char *packbuf;
606     int err, errs = 0, pack_size, type_size, position;
607
608     err = MPI_Type_size(datatype, &type_size);
609     if (err != MPI_SUCCESS) {
610         errs++;
611         if (verbose) {
612             fprintf(stderr, "error in MPI_Type_size call; aborting after %d errors\n", errs);
613         }
614         return errs;
615     }
616
617     type_size *= count;
618
619     err = MPI_Pack_size(count, datatype, MPI_COMM_SELF, &pack_size);
620     if (err != MPI_SUCCESS) {
621         errs++;
622         if (verbose) {
623             fprintf(stderr, "error in MPI_Pack_size call; aborting after %d errors\n", errs);
624         }
625         return errs;
626     }
627     packbuf = (char *) malloc(pack_size);
628     if (packbuf == NULL) {
629         errs++;
630         if (verbose) {
631             fprintf(stderr, "error in malloc call; aborting after %d errors\n", errs);
632         }
633         return errs;
634     }
635
636     position = 0;
637     err = MPI_Pack(typebuf, count, datatype, packbuf, type_size, &position, MPI_COMM_SELF);
638
639     if (position != type_size) {
640         errs++;
641         if (verbose)
642             fprintf(stderr, "position = %d; should be %d (pack)\n", position, type_size);
643     }
644
645     memset(typebuf, 0, typebufsz);
646     position = 0;
647     err = MPI_Unpack(packbuf, type_size, &position, typebuf, count, datatype, MPI_COMM_SELF);
648     if (err != MPI_SUCCESS) {
649         errs++;
650         if (verbose) {
651             fprintf(stderr, "error in MPI_Unpack call; aborting after %d errors\n", errs);
652         }
653         return errs;
654     }
655     free(packbuf);
656
657     if (position != type_size) {
658         errs++;
659         if (verbose)
660             fprintf(stderr, "position = %d; should be %d (unpack)\n", position, type_size);
661     }
662
663     return errs;
664 }
665
666 int parse_args(int argc, char **argv)
667 {
668     /*
669      * int ret;
670      *
671      * while ((ret = getopt(argc, argv, "v")) >= 0)
672      * {
673      * switch (ret) {
674      * case 'v':
675      * verbose = 1;
676      * break;
677      * }
678      * }
679      */
680     if (argc > 1 && strcmp(argv[1], "-v") == 0)
681         verbose = 1;
682     return 0;
683 }