Logo AND Algorithmique Numérique Distribuée

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