1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
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
14 #if !defined(USE_STRICT_MPI) && defined(MPICH2)
15 #define TEST_HINDEXED_BLOCK 1
16 #endif
17
18 static int verbose = 0;
19
20 /* tests */
21 int hindexed_block_contig_test(void);
22 int hindexed_block_vector_test(void);
23
24 /* helper functions */
25 int parse_args(int argc, char **argv);
26 static int pack_and_unpack(char *typebuf, int count, MPI_Datatype datatype, int typebufsz);
27
main(int argc,char ** argv)28 int main(int argc, char **argv)
29 {
30 int err, errs = 0;
31 int rank;
32
33 MPI_Init(&argc, &argv); /* MPI-1.2 doesn't allow for MPI_Init(0,0) */
34 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
35 #if defined(TEST_HINDEXED_BLOCK)
36 parse_args(argc, argv);
37
38 /* To improve reporting of problems about operations, we
39 * change the error handler to errors return */
40 MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
41
42 /* perform some tests */
43 err = hindexed_block_contig_test();
44 if (err && verbose)
45 fprintf(stderr, "%d errors in hindexed_block test.\n", err);
46 errs += err;
47
48 err = hindexed_block_vector_test();
49 if (err && verbose)
50 fprintf(stderr, "%d errors in hindexed_block vector test.\n", err);
51 errs += err;
52 #endif /*defined(TEST_HINDEXED_BLOCK)*/
53
54 /* print message and exit */
55 if (rank == 0) {
56 if (errs) {
57 fprintf(stderr, "Found %d errors\n", errs);
58 }
59 else {
60 printf(" No Errors\n");
61 }
62 }
63 MPI_Finalize();
64 return 0;
65 }
66
67 #if defined(TEST_HINDEXED_BLOCK)
68
69 /* hindexed_block_contig_test()
70 *
71 * Tests behavior with a hindexed_block that can be converted to a
72 * contig easily. This is specifically for coverage.
73 *
74 * Returns the number of errors encountered.
75 */
hindexed_block_contig_test(void)76 int hindexed_block_contig_test(void)
77 {
78 int buf[4] = { 7, -1, -2, -3 };
79 int err, errs = 0;
80
81 int i, count = 1;
82 MPI_Aint disp = 0;
83 MPI_Datatype newtype;
84
85 int size, int_size;
86 MPI_Aint extent;
87
88 err = MPIX_Type_create_hindexed_block(count, 1, &disp, MPI_INT, &newtype);
89 if (err != MPI_SUCCESS) {
90 if (verbose) {
91 fprintf(stderr, "error creating struct type in hindexed_block_contig_test()\n");
92 }
93 errs++;
94 }
95
96 MPI_Type_size(MPI_INT, &int_size);
97
98 err = MPI_Type_size(newtype, &size);
99 if (err != MPI_SUCCESS) {
100 if (verbose) {
101 fprintf(stderr, "error obtaining type size in hindexed_block_contig_test()\n");
102 }
103 errs++;
104 }
105
106 if (size != int_size) {
107 if (verbose) {
108 fprintf(stderr, "error: size != int_size in hindexed_block_contig_test()\n");
109 }
110 errs++;
111 }
112
113 err = MPI_Type_extent(newtype, &extent);
114 if (err != MPI_SUCCESS) {
115 if (verbose) {
116 fprintf(stderr, "error obtaining type extent in hindexed_block_contig_test()\n");
117 }
118 errs++;
119 }
120
121 if (extent != int_size) {
122 if (verbose) {
123 fprintf(stderr, "error: extent != int_size in hindexed_block_contig_test()\n");
124 }
125 errs++;
126 }
127
128 MPI_Type_commit(&newtype);
129
130 err = pack_and_unpack((char *) buf, 1, newtype, 4 * sizeof(int));
131 if (err != 0) {
132 if (verbose) {
133 fprintf(stderr, "error packing/unpacking in hindexed_block_contig_test()\n");
134 }
135 errs += err;
136 }
137
138 for (i = 0; i < 4; i++) {
139 int goodval;
140
141 switch (i) {
142 case 0:
143 goodval = 7;
144 break;
145 default:
146 goodval = 0; /* pack_and_unpack() zeros before unpack */
147 break;
148 }
149 if (buf[i] != goodval) {
150 errs++;
151 if (verbose)
152 fprintf(stderr, "buf[%d] = %d; should be %d\n", i, buf[i], goodval);
153 }
154 }
155
156 MPI_Type_free(&newtype);
157
158 return errs;
159 }
160
161 /* hindexed_block_vector_test()
162 *
163 * Tests behavior with a hindexed_block of some vector types;
164 * this shouldn't be easily convertable into anything else.
165 *
166 * Returns the number of errors encountered.
167 */
hindexed_block_vector_test(void)168 int hindexed_block_vector_test(void)
169 {
170 #define NELT (18)
171 int buf[NELT] = {
172 -1, -1, -1,
173 1, -2, 2,
174 -3, -3, -3,
175 -4, -4, -4,
176 3, -5, 4,
177 5, -6, 6
178 };
179 int expected[NELT] = {
180 0, 0, 0,
181 1, 0, 2,
182 0, 0, 0,
183 0, 0, 0,
184 3, 0, 4,
185 5, 0, 6
186 };
187 int err, errs = 0;
188
189 int i, count = 3;
190 MPI_Aint disp[] = { 1, 4, 5 };
191 MPI_Datatype vectype, newtype;
192
193 int size, int_size;
194 MPI_Aint extent;
195
196 /* create a vector type of 2 ints, skipping one in between */
197 err = MPI_Type_vector(2, 1, 2, MPI_INT, &vectype);
198 if (err != MPI_SUCCESS) {
199 if (verbose) {
200 fprintf(stderr, "error creating vector type in hindexed_block_contig_test()\n");
201 }
202 errs++;
203 }
204
205 MPI_Type_commit(&vectype);
206
207 MPI_Type_extent(vectype, &extent);
208 for (i = 0; i < count; i++)
209 disp[i] *= extent;
210
211 err = MPIX_Type_create_hindexed_block(count, 1, disp, vectype, &newtype);
212 if (err != MPI_SUCCESS) {
213 if (verbose) {
214 fprintf(stderr,
215 "error creating hindexed_block type in hindexed_block_contig_test()\n");
216 }
217 errs++;
218 }
219
220 MPI_Type_commit(&newtype);
221
222 err = MPI_Type_size(newtype, &size);
223 if (err != MPI_SUCCESS) {
224 if (verbose) {
225 fprintf(stderr, "error obtaining type size in hindexed_block_contig_test()\n");
226 }
227 errs++;
228 }
229
230 MPI_Type_size(MPI_INT, &int_size);
231
232 if (size != 6 * int_size) {
233 if (verbose) {
234 fprintf(stderr, "error: size != 6 * int_size in hindexed_block_contig_test()\n");
235 }
236 errs++;
237 }
238
239 MPI_Type_extent(newtype, &extent);
240
241 err = pack_and_unpack((char *) buf, 1, newtype, NELT * sizeof(int));
242 if (err != 0) {
243 if (verbose) {
244 fprintf(stderr, "error packing/unpacking in hindexed_block_vector_test()\n");
245 }
246 errs += err;
247 }
248
249 for (i = 0; i < NELT; i++) {
250 if (buf[i] != expected[i]) {
251 errs++;
252 if (verbose)
253 fprintf(stderr, "buf[%d] = %d; should be %d\n", i, buf[i], expected[i]);
254 }
255 }
256
257 MPI_Type_free(&vectype);
258 MPI_Type_free(&newtype);
259 return errs;
260 }
261
262
263 /* pack_and_unpack()
264 *
265 * Perform packing and unpacking of a buffer for the purposes of checking
266 * to see if we are processing a type correctly. Zeros the buffer between
267 * these two operations, so the data described by the type should be in
268 * place upon return but all other regions of the buffer should be zero.
269 *
270 * Parameters:
271 * typebuf - pointer to buffer described by datatype and count that
272 * will be packed and then unpacked into
273 * count, datatype - description of typebuf
274 * typebufsz - size of typebuf; used specifically to zero the buffer
275 * between the pack and unpack steps
276 *
277 */
pack_and_unpack(char * typebuf,int count,MPI_Datatype datatype,int typebufsz)278 static int pack_and_unpack(char *typebuf, int count, MPI_Datatype datatype, int typebufsz)
279 {
280 char *packbuf;
281 int err, errs = 0, pack_size, type_size, position;
282
283 err = MPI_Type_size(datatype, &type_size);
284 if (err != MPI_SUCCESS) {
285 errs++;
286 if (verbose) {
287 fprintf(stderr, "error in MPI_Type_size call; aborting after %d errors\n", errs);
288 }
289 return errs;
290 }
291
292 type_size *= count;
293
294 err = MPI_Pack_size(count, datatype, MPI_COMM_SELF, &pack_size);
295 if (err != MPI_SUCCESS) {
296 errs++;
297 if (verbose) {
298 fprintf(stderr, "error in MPI_Pack_size call; aborting after %d errors\n", errs);
299 }
300 return errs;
301 }
302 packbuf = (char *) malloc(pack_size);
303 if (packbuf == NULL) {
304 errs++;
305 if (verbose) {
306 fprintf(stderr, "error in malloc call; aborting after %d errors\n", errs);
307 }
308 return errs;
309 }
310
311 position = 0;
312 err = MPI_Pack(typebuf, count, datatype, packbuf, type_size, &position, MPI_COMM_SELF);
313
314 if (position != type_size) {
315 errs++;
316 if (verbose)
317 fprintf(stderr, "position = %d; should be %d (pack)\n", position, type_size);
318 }
319
320 memset(typebuf, 0, typebufsz);
321 position = 0;
322 err = MPI_Unpack(packbuf, type_size, &position, typebuf, count, datatype, MPI_COMM_SELF);
323 if (err != MPI_SUCCESS) {
324 errs++;
325 if (verbose) {
326 fprintf(stderr, "error in MPI_Unpack call; aborting after %d errors\n", errs);
327 }
328 return errs;
329 }
330 free(packbuf);
331
332 if (position != type_size) {
333 errs++;
334 if (verbose)
335 fprintf(stderr, "position = %d; should be %d (unpack)\n", position, type_size);
336 }
337
338 return errs;
339 }
340
parse_args(int argc,char ** argv)341 int parse_args(int argc, char **argv)
342 {
343 if (argc > 1 && strcmp(argv[1], "-v") == 0)
344 verbose = 1;
345 return 0;
346 }
347 #endif /*defined(TEST_HINDEXED_BLOCK)*/
348