1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3 * (C) 2012 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "mpi.h"
11 #include "mpitest.h"
12
13 /* This is a temporary #ifdef to control whether we test this functionality. A
14 * configure-test or similar would be better. Eventually the MPI-3 standard
15 * will be released and this can be gated on a MPI_VERSION check */
16 #if !defined(USE_STRICT_MPI) && defined(MPICH2)
17 #define TEST_MPROBE_ROUTINES 1
18 #endif
19
20 /* assert-like macro that bumps the err count and emits a message */
21 #define check(x_) \
22 do { \
23 if (!(x_)) { \
24 ++errs; \
25 if (errs < 10) { \
26 fprintf(stderr, "check failed: (%s), line %d\n", #x_, __LINE__); \
27 } \
28 } \
29 } while (0)
30
main(int argc,char ** argv)31 int main(int argc, char **argv)
32 {
33 int errs = 0;
34 int found, completed;
35 int rank, size;
36 int sendbuf[8], recvbuf[8];
37 int count;
38 #ifdef TEST_MPROBE_ROUTINES
39 MPIX_Message msg;
40 #endif
41 MPI_Request rreq;
42 MPI_Status s1, s2;
43
44 MPI_Init(&argc, &argv);
45
46 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
47 MPI_Comm_size(MPI_COMM_WORLD, &size);
48
49 if (size < 2) {
50 printf("this test requires at least 2 processes\n");
51 MPI_Abort(MPI_COMM_WORLD, 1);
52 }
53
54 /* all processes besides ranks 0 & 1 aren't used by this test */
55 if (rank >= 2) {
56 goto epilogue;
57 }
58
59 #ifdef TEST_MPROBE_ROUTINES
60 /* test 0: simple send & mprobe+mrecv */
61 if (rank == 0) {
62 sendbuf[0] = 0xdeadbeef;
63 sendbuf[1] = 0xfeedface;
64 MPI_Send(sendbuf, 2, MPI_INT, 1, 5, MPI_COMM_WORLD);
65 }
66 else {
67 memset(&s1, 0xab, sizeof(MPI_Status));
68 memset(&s2, 0xab, sizeof(MPI_Status));
69 /* the error field should remain unmodified */
70 s1.MPI_ERROR = MPI_ERR_DIMS;
71 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
72
73 msg = MPIX_MESSAGE_NULL;
74 MPIX_Mprobe(0, 5, MPI_COMM_WORLD, &msg, &s1);
75 check(s1.MPI_SOURCE == 0);
76 check(s1.MPI_TAG == 5);
77 check(s1.MPI_ERROR == MPI_ERR_DIMS);
78 check(msg != MPIX_MESSAGE_NULL);
79
80 count = -1;
81 MPI_Get_count(&s1, MPI_INT, &count);
82 check(count == 2);
83
84 recvbuf[0] = 0x01234567;
85 recvbuf[1] = 0x89abcdef;
86 MPIX_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
87 check(recvbuf[0] == 0xdeadbeef);
88 check(recvbuf[1] == 0xfeedface);
89 check(s2.MPI_SOURCE == 0);
90 check(s2.MPI_TAG == 5);
91 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
92 check(msg == MPIX_MESSAGE_NULL);
93 }
94
95 /* test 1: simple send & mprobe+imrecv */
96 if (rank == 0) {
97 sendbuf[0] = 0xdeadbeef;
98 sendbuf[1] = 0xfeedface;
99 MPI_Send(sendbuf, 2, MPI_INT, 1, 5, MPI_COMM_WORLD);
100 }
101 else {
102 memset(&s1, 0xab, sizeof(MPI_Status));
103 memset(&s2, 0xab, sizeof(MPI_Status));
104 /* the error field should remain unmodified */
105 s1.MPI_ERROR = MPI_ERR_DIMS;
106 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
107
108 msg = MPIX_MESSAGE_NULL;
109 MPIX_Mprobe(0, 5, MPI_COMM_WORLD, &msg, &s1);
110 check(s1.MPI_SOURCE == 0);
111 check(s1.MPI_TAG == 5);
112 check(s1.MPI_ERROR == MPI_ERR_DIMS);
113 check(msg != MPIX_MESSAGE_NULL);
114
115 count = -1;
116 MPI_Get_count(&s1, MPI_INT, &count);
117 check(count == 2);
118
119 rreq = MPI_REQUEST_NULL;
120 recvbuf[0] = 0x01234567;
121 recvbuf[1] = 0x89abcdef;
122 MPIX_Imrecv(recvbuf, count, MPI_INT, &msg, &rreq);
123 check(rreq != MPI_REQUEST_NULL);
124 MPI_Wait(&rreq, &s2);
125 check(recvbuf[0] == 0xdeadbeef);
126 check(recvbuf[1] == 0xfeedface);
127 check(s2.MPI_SOURCE == 0);
128 check(s2.MPI_TAG == 5);
129 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
130 check(msg == MPIX_MESSAGE_NULL);
131 }
132
133 /* test 2: simple send & improbe+mrecv */
134 if (rank == 0) {
135 sendbuf[0] = 0xdeadbeef;
136 sendbuf[1] = 0xfeedface;
137 MPI_Send(sendbuf, 2, MPI_INT, 1, 5, MPI_COMM_WORLD);
138 }
139 else {
140 memset(&s1, 0xab, sizeof(MPI_Status));
141 memset(&s2, 0xab, sizeof(MPI_Status));
142 /* the error field should remain unmodified */
143 s1.MPI_ERROR = MPI_ERR_DIMS;
144 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
145
146 msg = MPIX_MESSAGE_NULL;
147 do {
148 check(msg == MPIX_MESSAGE_NULL);
149 MPIX_Improbe(0, 5, MPI_COMM_WORLD, &found, &msg, &s1);
150 } while (!found);
151 check(msg != MPIX_MESSAGE_NULL);
152 check(s1.MPI_SOURCE == 0);
153 check(s1.MPI_TAG == 5);
154 check(s1.MPI_ERROR == MPI_ERR_DIMS);
155
156 count = -1;
157 MPI_Get_count(&s1, MPI_INT, &count);
158 check(count == 2);
159
160 recvbuf[0] = 0x01234567;
161 recvbuf[1] = 0x89abcdef;
162 MPIX_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
163 check(recvbuf[0] == 0xdeadbeef);
164 check(recvbuf[1] == 0xfeedface);
165 check(s2.MPI_SOURCE == 0);
166 check(s2.MPI_TAG == 5);
167 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
168 check(msg == MPIX_MESSAGE_NULL);
169 }
170
171 /* test 3: simple send & improbe+imrecv */
172 if (rank == 0) {
173 sendbuf[0] = 0xdeadbeef;
174 sendbuf[1] = 0xfeedface;
175 MPI_Send(sendbuf, 2, MPI_INT, 1, 5, MPI_COMM_WORLD);
176 }
177 else {
178 memset(&s1, 0xab, sizeof(MPI_Status));
179 memset(&s2, 0xab, sizeof(MPI_Status));
180 /* the error field should remain unmodified */
181 s1.MPI_ERROR = MPI_ERR_DIMS;
182 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
183
184 msg = MPIX_MESSAGE_NULL;
185 do {
186 check(msg == MPIX_MESSAGE_NULL);
187 MPIX_Improbe(0, 5, MPI_COMM_WORLD, &found, &msg, &s1);
188 } while (!found);
189 check(msg != MPIX_MESSAGE_NULL);
190 check(s1.MPI_SOURCE == 0);
191 check(s1.MPI_TAG == 5);
192 check(s1.MPI_ERROR == MPI_ERR_DIMS);
193
194 count = -1;
195 MPI_Get_count(&s1, MPI_INT, &count);
196 check(count == 2);
197
198 rreq = MPI_REQUEST_NULL;
199 MPIX_Imrecv(recvbuf, count, MPI_INT, &msg, &rreq);
200 check(rreq != MPI_REQUEST_NULL);
201 MPI_Wait(&rreq, &s2);
202 check(recvbuf[0] == 0xdeadbeef);
203 check(recvbuf[1] == 0xfeedface);
204 check(s2.MPI_SOURCE == 0);
205 check(s2.MPI_TAG == 5);
206 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
207 check(msg == MPIX_MESSAGE_NULL);
208 }
209
210 /* test 4: mprobe+mrecv with MPI_PROC_NULL */
211 {
212 memset(&s1, 0xab, sizeof(MPI_Status));
213 memset(&s2, 0xab, sizeof(MPI_Status));
214 /* the error field should remain unmodified */
215 s1.MPI_ERROR = MPI_ERR_DIMS;
216 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
217
218 msg = MPIX_MESSAGE_NULL;
219 MPIX_Mprobe(MPI_PROC_NULL, 5, MPI_COMM_WORLD, &msg, &s1);
220 check(s1.MPI_SOURCE == MPI_PROC_NULL);
221 check(s1.MPI_TAG == MPI_ANY_TAG);
222 check(s1.MPI_ERROR == MPI_ERR_DIMS);
223 check(msg == MPIX_MESSAGE_NO_PROC);
224
225 count = -1;
226 MPI_Get_count(&s1, MPI_INT, &count);
227 check(count == 0);
228
229 recvbuf[0] = 0x01234567;
230 recvbuf[1] = 0x89abcdef;
231 MPIX_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
232 /* recvbuf should remain unmodified */
233 check(recvbuf[0] == 0x01234567);
234 check(recvbuf[1] == 0x89abcdef);
235 /* should get back "proc null status" */
236 check(s2.MPI_SOURCE == MPI_PROC_NULL);
237 check(s2.MPI_TAG == MPI_ANY_TAG);
238 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
239 check(msg == MPIX_MESSAGE_NULL);
240 count = -1;
241 MPI_Get_count(&s2, MPI_INT, &count);
242 check(count == 0);
243 }
244
245 /* test 5: mprobe+imrecv with MPI_PROC_NULL */
246 {
247 memset(&s1, 0xab, sizeof(MPI_Status));
248 memset(&s2, 0xab, sizeof(MPI_Status));
249 /* the error field should remain unmodified */
250 s1.MPI_ERROR = MPI_ERR_DIMS;
251 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
252
253 msg = MPIX_MESSAGE_NULL;
254 MPIX_Mprobe(MPI_PROC_NULL, 5, MPI_COMM_WORLD, &msg, &s1);
255 check(s1.MPI_SOURCE == MPI_PROC_NULL);
256 check(s1.MPI_TAG == MPI_ANY_TAG);
257 check(s1.MPI_ERROR == MPI_ERR_DIMS);
258 check(msg == MPIX_MESSAGE_NO_PROC);
259 count = -1;
260 MPI_Get_count(&s1, MPI_INT, &count);
261 check(count == 0);
262
263 rreq = MPI_REQUEST_NULL;
264 recvbuf[0] = 0x01234567;
265 recvbuf[1] = 0x89abcdef;
266 MPIX_Imrecv(recvbuf, count, MPI_INT, &msg, &rreq);
267 check(rreq != MPI_REQUEST_NULL);
268 completed = 0;
269 MPI_Test(&rreq, &completed, &s2); /* single test should always succeed */
270 check(completed);
271 /* recvbuf should remain unmodified */
272 check(recvbuf[0] == 0x01234567);
273 check(recvbuf[1] == 0x89abcdef);
274 /* should get back "proc null status" */
275 check(s2.MPI_SOURCE == MPI_PROC_NULL);
276 check(s2.MPI_TAG == MPI_ANY_TAG);
277 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
278 check(msg == MPIX_MESSAGE_NULL);
279 count = -1;
280 MPI_Get_count(&s2, MPI_INT, &count);
281 check(count == 0);
282 }
283
284 /* test 6: improbe+mrecv with MPI_PROC_NULL */
285 {
286 memset(&s1, 0xab, sizeof(MPI_Status));
287 memset(&s2, 0xab, sizeof(MPI_Status));
288 /* the error field should remain unmodified */
289 s1.MPI_ERROR = MPI_ERR_DIMS;
290 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
291
292 msg = MPIX_MESSAGE_NULL;
293 found = 0;
294 MPIX_Improbe(MPI_PROC_NULL, 5, MPI_COMM_WORLD, &found, &msg, &s1);
295 check(found);
296 check(msg == MPIX_MESSAGE_NO_PROC);
297 check(s1.MPI_SOURCE == MPI_PROC_NULL);
298 check(s1.MPI_TAG == MPI_ANY_TAG);
299 check(s1.MPI_ERROR == MPI_ERR_DIMS);
300 count = -1;
301 MPI_Get_count(&s1, MPI_INT, &count);
302 check(count == 0);
303
304 recvbuf[0] = 0x01234567;
305 recvbuf[1] = 0x89abcdef;
306 MPIX_Mrecv(recvbuf, count, MPI_INT, &msg, &s2);
307 /* recvbuf should remain unmodified */
308 check(recvbuf[0] == 0x01234567);
309 check(recvbuf[1] == 0x89abcdef);
310 /* should get back "proc null status" */
311 check(s2.MPI_SOURCE == MPI_PROC_NULL);
312 check(s2.MPI_TAG == MPI_ANY_TAG);
313 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
314 check(msg == MPIX_MESSAGE_NULL);
315 count = -1;
316 MPI_Get_count(&s2, MPI_INT, &count);
317 check(count == 0);
318 }
319
320 /* test 7: improbe+imrecv */
321 {
322 memset(&s1, 0xab, sizeof(MPI_Status));
323 memset(&s2, 0xab, sizeof(MPI_Status));
324 /* the error field should remain unmodified */
325 s1.MPI_ERROR = MPI_ERR_DIMS;
326 s2.MPI_ERROR = MPI_ERR_TOPOLOGY;
327
328 msg = MPIX_MESSAGE_NULL;
329 MPIX_Improbe(MPI_PROC_NULL, 5, MPI_COMM_WORLD, &found, &msg, &s1);
330 check(found);
331 check(msg == MPIX_MESSAGE_NO_PROC);
332 check(s1.MPI_SOURCE == MPI_PROC_NULL);
333 check(s1.MPI_TAG == MPI_ANY_TAG);
334 check(s1.MPI_ERROR == MPI_ERR_DIMS);
335 count = -1;
336 MPI_Get_count(&s1, MPI_INT, &count);
337 check(count == 0);
338
339 rreq = MPI_REQUEST_NULL;
340 MPIX_Imrecv(recvbuf, count, MPI_INT, &msg, &rreq);
341 check(rreq != MPI_REQUEST_NULL);
342 completed = 0;
343 MPI_Test(&rreq, &completed, &s2); /* single test should always succeed */
344 check(completed);
345 /* recvbuf should remain unmodified */
346 check(recvbuf[0] == 0x01234567);
347 check(recvbuf[1] == 0x89abcdef);
348 /* should get back "proc null status" */
349 check(s2.MPI_SOURCE == MPI_PROC_NULL);
350 check(s2.MPI_TAG == MPI_ANY_TAG);
351 check(s2.MPI_ERROR == MPI_ERR_TOPOLOGY);
352 check(msg == MPIX_MESSAGE_NULL);
353 count = -1;
354 MPI_Get_count(&s2, MPI_INT, &count);
355 check(count == 0);
356 }
357
358 /* TODO MPI_ANY_SOURCE and MPI_ANY_TAG should be tested as well */
359 /* TODO a full range of message sizes should be tested too */
360 /* TODO threaded tests are also needed, but they should go in a separate
361 * program */
362
363 /* simple test to ensure that c2f/f2c routines are present (initially missed
364 * in MPICH2 impl) */
365 {
366 MPI_Fint f_handle = 0xdeadbeef;
367 f_handle = MPIX_Message_c2f(MPIX_MESSAGE_NULL);
368 msg = MPIX_Message_f2c(f_handle);
369 check(f_handle != 0xdeadbeef);
370 check(msg == MPIX_MESSAGE_NULL);
371
372 /* PMPIX_ versions should also exists */
373 f_handle = 0xdeadbeef;
374 f_handle = PMPIX_Message_c2f(MPIX_MESSAGE_NULL);
375 msg = PMPIX_Message_f2c(f_handle);
376 check(f_handle != 0xdeadbeef);
377 check(msg == MPIX_MESSAGE_NULL);
378 }
379
380 #endif /* TEST_MPROBE_ROUTINES */
381
382 epilogue:
383 MPI_Reduce((rank == 0 ? MPI_IN_PLACE : &errs), &errs, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
384 if (rank == 0) {
385 if (errs) {
386 printf("found %d errors\n", errs);
387 }
388 else {
389 printf(" No errors\n");
390 }
391 }
392
393 MPI_Finalize();
394
395 return 0;
396 }
397
398