1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2001 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
9 #include "mpitestconf.h"
16 static int verbose = 1;
18 #define check(cond_) \
22 fprintf(stderr, "condition '%s' does not hold, at line %d\n", #cond_, __LINE__); \
28 #define check_err(err_, what_failed_) \
32 fprintf(stderr, "error: %s, at line %d\n", (what_failed_), __LINE__); \
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);
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);
50 int main(int argc, char **argv)
54 MPI_Init(&argc, &argv); /* MPI-1.2 doesn't allow for MPI_Init(0,0) */
55 parse_args(argc, argv);
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);
61 /* perform some tests */
62 err = indexed_contig_test();
64 fprintf(stderr, "%d errors in indexed_contig_test.\n", err);
67 err = indexed_zeroblock_first_test();
69 fprintf(stderr, "%d errors in indexed_zeroblock_first_test.\n", err);
72 err = indexed_zeroblock_middle_test();
74 fprintf(stderr, "%d errors in indexed_zeroblock_middle_test.\n", err);
77 err = indexed_zeroblock_last_test();
79 fprintf(stderr, "%d errors in indexed_zeroblock_last_test.\n", err);
82 err = indexed_contig_leading_zero_test();
84 fprintf(stderr, "%d errors in indexed_contig_leading_zero_test.\n", err);
87 err = indexed_same_lengths();
89 fprintf(stderr, "%d errors in indexed_contig_leading_zero_test.\n", err);
92 /* print message and exit */
94 fprintf(stderr, "Found %d errors\n", errs);
97 printf(" No Errors\n");
103 int indexed_zeroblock_first_test(void)
108 int len[3] = { 0, 1, 1 };
109 int disp[3] = { 0, 1, 4 };
112 err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
113 if (err != MPI_SUCCESS) {
115 fprintf(stderr, "error creating indexed type in indexed_zeroblock_first_test()\n");
120 MPI_Type_lb(type, &lb);
121 if (lb != sizeof(int)) {
123 fprintf(stderr, "lb mismatch; is %d, should be %d\n", (int) lb, (int) sizeof(int));
127 MPI_Type_ub(type, &ub);
128 if (ub != 5 * sizeof(int)) {
131 "ub mismatch; is %d, should be %d\n", (int) ub, (int) (5 * sizeof(int)));
136 MPI_Type_free(&type);
141 int indexed_zeroblock_middle_test(void)
146 int len[3] = { 1, 0, 1 };
147 int disp[3] = { 1, 2, 4 };
150 err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
151 if (err != MPI_SUCCESS) {
153 fprintf(stderr, "error creating indexed type in indexed_zeroblock_middle_test()\n");
158 MPI_Type_lb(type, &lb);
159 if (lb != sizeof(int)) {
161 fprintf(stderr, "lb mismatch; is %d, should be %d\n", (int) lb, (int) sizeof(int));
165 MPI_Type_ub(type, &ub);
166 if (ub != 5 * sizeof(int)) {
169 "ub mismatch; is %d, should be %d\n", (int) ub, (int) (5 * sizeof(int)));
174 MPI_Type_free(&type);
179 int indexed_zeroblock_last_test(void)
184 int len[3] = { 1, 1, 0 };
185 int disp[3] = { 1, 4, 8 };
188 err = MPI_Type_indexed(3, len, disp, MPI_INT, &type);
189 if (err != MPI_SUCCESS) {
191 fprintf(stderr, "error creating indexed type in indexed_zeroblock_last_test()\n");
196 MPI_Type_lb(type, &lb);
197 if (lb != sizeof(int)) {
199 fprintf(stderr, "lb mismatch; is %d, should be %d\n", (int) lb, (int) sizeof(int));
203 MPI_Type_ub(type, &ub);
204 if (ub != 5 * sizeof(int)) {
207 "ub mismatch; is %d, should be %d\n", (int) ub, (int) (5 * sizeof(int)));
212 MPI_Type_free(&type);
217 /* indexed_contig_test()
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.
222 * Returns the number of errors encountered.
224 int indexed_contig_test(void)
226 int buf[9] = { -1, 1, 2, 3, -2, 4, 5, -3, 6 };
230 int blklen[] = { 1, 2, 1, 1, 1 };
231 int disp[] = { 1, 2, 5, 6, 8 };
232 MPI_Datatype newtype;
236 err = MPI_Type_indexed(count, blklen, disp, MPI_INT, &newtype);
237 if (err != MPI_SUCCESS) {
239 fprintf(stderr, "error creating indexed type in indexed_contig_test()\n");
244 MPI_Type_size(MPI_INT, &int_size);
246 err = MPI_Type_size(newtype, &size);
247 if (err != MPI_SUCCESS) {
249 fprintf(stderr, "error obtaining type size in indexed_contig_test()\n");
254 if (size != 6 * int_size) {
256 fprintf(stderr, "error: size != 6 * int_size in indexed_contig_test()\n");
261 MPI_Type_commit(&newtype);
263 err = pack_and_unpack((char *) buf, 1, newtype, 9 * sizeof(int));
266 fprintf(stderr, "error packing/unpacking in indexed_contig_test()\n");
271 for (i = 0; i < 9; i++) {
294 goodval = 0; /* pack_and_unpack() zeros before unpack */
297 if (buf[i] != goodval) {
300 fprintf(stderr, "buf[%d] = %d; should be %d\n", i, buf[i], goodval);
304 MPI_Type_free(&newtype);
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)
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 };
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()");
331 MPI_Type_lb(type, &lb);
332 check(lb == 2 * sizeof(int));
333 MPI_Type_ub(type, &ub);
334 check(ub == 6 * sizeof(int));
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));
340 for (i = 0; i < 10; ++i) {
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) {
351 check(buf[i] == expected);
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) */
362 adisp[1] = 8 * sizeof(int);
366 /* struct layout: xx0123xx4x ('x' indicates a hole), one char is an
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()");
373 buf = malloc(10 * sizeof(int));
375 for (i = 0; i < 10; ++i) {
378 err = pack_and_unpack((char *) buf, 1, struct_type, 10 * sizeof(int));
379 check_err(err, "packing/unpacking in indexed_contig_test()");
381 for (i = 0; i < 10; ++i) {
383 if ((i >= 2 && i < 6) || i == 8)
387 check(buf[i] == expected);
391 MPI_Type_free(&struct_type);
392 MPI_Type_free(&type);
394 /* -------------------------------------------------------------------- */
395 /* now do the same as above, but with hindexed */
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;
411 adisp[0] = (MPI_Aint) INT_MAX;
412 adisp[1] = 2 * sizeof(int);
413 adisp[2] = (MPI_Aint) INT_MAX;
416 err = MPI_Type_hindexed(3, len, adisp, MPI_INT, &type);
417 check_err(err, "creating hindexed type in indexed_contig_leading_zero_test()");
419 err = MPI_Type_commit(&type);
420 check_err(err, "committing hindexed type in indexed_contig_leading_zero_test()");
422 MPI_Type_lb(type, &lb);
423 check(lb == 2 * sizeof(int));
424 MPI_Type_ub(type, &ub);
425 check(ub == 6 * sizeof(int));
427 buf = malloc(10 * sizeof(int));
429 for (i = 0; i < 10; ++i) {
432 err = pack_and_unpack((char *) buf, 1, type, 10 * sizeof(int));
433 check_err(err, "packing/unpacking in indexed_contig_test()");
435 for (i = 0; i < 10; ++i) {
441 check(buf[i] == expected);
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) */
453 adisp[1] = 8 * sizeof(int);
455 /* struct layout: xx0123xx4x ('x' indicates a hole), one char is an
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()");
462 buf = malloc(10 * sizeof(int));
464 for (i = 0; i < 10; ++i) {
467 /* fails in old MPICH (3.0rc1 and earlier), despite correct ub/lb
469 err = pack_and_unpack((char *) buf, 1, struct_type, 10 * sizeof(int));
470 check_err(err, "packing/unpacking in indexed_contig_test()");
472 for (i = 0; i < 10; ++i) {
474 if ((i >= 2 && i < 6) || i == 8)
478 check(buf[i] == expected);
482 MPI_Type_free(&struct_type);
483 MPI_Type_free(&type);
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)
498 MPI_Datatype type = MPI_DATATYPE_NULL;
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()");
520 MPI_Type_lb(type, &lb);
521 check(lb == 1 * sizeof(int));
522 MPI_Type_ub(type, &ub);
523 check(ub == 9 * sizeof(int));
525 buf = malloc(10 * sizeof(int));
527 for (i = 0; i < 10; ++i) {
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) {
534 if (i == 1 || i == 3 || i == 8)
538 check(buf[i] == expected);
542 MPI_Type_free(&type);
544 /* -------------------------------------------------------------------- */
545 /* now do the same as above, but with hindexed */
551 adisp[0] = 0 * sizeof(int);
552 adisp[1] = 1 * sizeof(int);
553 adisp[2] = 3 * sizeof(int);
554 adisp[3] = 8 * sizeof(int);
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()");
561 MPI_Type_lb(type, &lb);
562 check(lb == 1 * sizeof(int));
563 MPI_Type_ub(type, &ub);
564 check(ub == 9 * sizeof(int));
566 buf = malloc(10 * sizeof(int));
568 for (i = 0; i < 10; ++i) {
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) {
575 if (i == 1 || i == 3 || i == 8)
579 check(buf[i] == expected);
583 MPI_Type_free(&type);
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.
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
603 static int pack_and_unpack(char *typebuf, int count, MPI_Datatype datatype, int typebufsz)
606 int err, errs = 0, pack_size, type_size, position;
608 err = MPI_Type_size(datatype, &type_size);
609 if (err != MPI_SUCCESS) {
612 fprintf(stderr, "error in MPI_Type_size call; aborting after %d errors\n", errs);
619 err = MPI_Pack_size(count, datatype, MPI_COMM_SELF, &pack_size);
620 if (err != MPI_SUCCESS) {
623 fprintf(stderr, "error in MPI_Pack_size call; aborting after %d errors\n", errs);
627 packbuf = (char *) malloc(pack_size);
628 if (packbuf == NULL) {
631 fprintf(stderr, "error in malloc call; aborting after %d errors\n", errs);
637 err = MPI_Pack(typebuf, count, datatype, packbuf, type_size, &position, MPI_COMM_SELF);
639 if (position != type_size) {
642 fprintf(stderr, "position = %d; should be %d (pack)\n", position, type_size);
645 memset(typebuf, 0, typebufsz);
647 err = MPI_Unpack(packbuf, type_size, &position, typebuf, count, datatype, MPI_COMM_SELF);
648 if (err != MPI_SUCCESS) {
651 fprintf(stderr, "error in MPI_Unpack call; aborting after %d errors\n", errs);
657 if (position != type_size) {
660 fprintf(stderr, "position = %d; should be %d (unpack)\n", position, type_size);
666 int parse_args(int argc, char **argv)
671 * while ((ret = getopt(argc, argv, "v")) >= 0)
680 if (argc > 1 && strcmp(argv[1], "-v") == 0)