YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
test_expect_abort.c
Go to the documentation of this file.
1// Copyright (c) 2026 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <mpi.h>
6
7#include "tests.h"
8#include "test_expect_abort.h"
9#include "ppm/core.h"
10
17static char const * expected_msg = "ERROR(dummy): the expected message";
18static char const * unexpected_msg = "ERROR(dummy): some other message";
19static char const * expected_substr = "the expected message";
20
21static void utest_maybe_abort(int do_abort, char const * msg) {
22
23 if (do_abort) yac_abort(MPI_COMM_WORLD, msg, __FILE__, __LINE__);
24}
25
26static void utest_check(int test_failed, char const * test_name) {
27
28 if (test_failed) PUT_ERR_F("ERROR in %s", test_name);
29}
30
31int main(void) {
32
33 MPI_Init(NULL, NULL);
34
35 int comm_rank, comm_size;
36 MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
37 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
38
39 if (comm_size != 2) {
40 PUT_ERR("ERROR: wrong number of processes (has to be 2)");
41 MPI_Finalize();
42 return TEST_EXIT_CODE;
43 }
44
45 yac_abort_func initial_handler = yac_get_abort_handler();
46
47 int test_failed;
48
49 { // serial: statement does not abort
50
53 utest_maybe_abort(0, expected_msg));
54 utest_check(test_failed, "SERIAL without abort");
55 }
56
57 { // serial: statement aborts with the expected message
58
61 utest_maybe_abort(1, expected_msg));
62 utest_check(test_failed, "SERIAL with abort");
63 }
64
65 { // serial: statement aborts with an unexpected message
66
69 utest_maybe_abort(1, unexpected_msg));
70 utest_check(test_failed, "SERIAL with unexpected message");
71 }
72
73 { // serial: any message is accepted if no substring is provided
74
76 test_failed, YAC_TEST_ABORT_EXPECTED, NULL,
77 utest_maybe_abort(1, unexpected_msg));
78 utest_check(test_failed, "SERIAL without substring");
79 }
80
81 { // serial: the statement may contain commas at bracket level zero
82
83 // volatile because the value is modified between setjmp and longjmp
84 // and read afterwards (C11 7.13.2.1)
85 int volatile statement_was_executed = 0;
88 statement_was_executed = 1, utest_maybe_abort(1, expected_msg));
89 utest_check(test_failed, "SERIAL with comma");
90#if YAC_TEST_ABORT_UNHAPPY_PATH_ENABLED
91 if (!statement_was_executed)
92 PUT_ERR("ERROR in SERIAL with comma: statement was not executed");
93#else
94 if (statement_was_executed)
95 PUT_ERR("ERROR in SERIAL with comma: statement was executed");
96#endif
97 }
98
99 // the abort handler has to be restored by every macro
100 if (yac_get_abort_handler() != initial_handler)
101 PUT_ERR("ERROR: abort handler was not restored");
102
103 { // parallel: no process aborts
104
106 test_failed, YAC_TEST_ABORT_NO_CALL, expected_substr, MPI_COMM_WORLD,
107 utest_maybe_abort(0, expected_msg));
108 utest_check(test_failed, "PAR_ANY without abort");
109
111 test_failed, YAC_TEST_ABORT_NO_CALL, expected_substr, MPI_COMM_WORLD,
112 utest_maybe_abort(0, expected_msg));
113 utest_check(test_failed, "PAR_ALL without abort");
114 }
115
116 { // parallel: all processes abort with the expected message
117
119 test_failed, YAC_TEST_ABORT_EXPECTED, expected_substr, MPI_COMM_WORLD,
120 utest_maybe_abort(1, expected_msg));
121 utest_check(test_failed, "PAR_ANY with all aborting");
122
124 test_failed, YAC_TEST_ABORT_EXPECTED, expected_substr, MPI_COMM_WORLD,
125 utest_maybe_abort(1, expected_msg));
126 utest_check(test_failed, "PAR_ALL with all aborting");
127 }
128
129 { // parallel: only one process aborts with the expected message
130
132 test_failed, YAC_TEST_ABORT_EXPECTED, expected_substr, MPI_COMM_WORLD,
133 utest_maybe_abort(comm_rank == 0, expected_msg));
134 utest_check(test_failed, "PAR_ANY with one aborting");
135
136 // PAR_ALL requires all processes to abort
138 test_failed, YAC_TEST_ABORT_UNEXPECTED, expected_substr, MPI_COMM_WORLD,
139 utest_maybe_abort(comm_rank == 0, expected_msg));
140 utest_check(test_failed, "PAR_ALL with one aborting");
141 }
142
143 { // parallel: all processes abort, but one with an unexpected message
144 // (an unexpected message must not be masked by the other processes)
145
147 test_failed, YAC_TEST_ABORT_UNEXPECTED, expected_substr, MPI_COMM_WORLD,
148 utest_maybe_abort(1, (comm_rank == 0)?expected_msg:unexpected_msg));
149 utest_check(test_failed, "PAR_ANY with mixed messages");
150
152 test_failed, YAC_TEST_ABORT_UNEXPECTED, expected_substr, MPI_COMM_WORLD,
153 utest_maybe_abort(1, (comm_rank == 0)?expected_msg:unexpected_msg));
154 utest_check(test_failed, "PAR_ALL with mixed messages");
155 }
156
157 { // statements that are expected to abort are not executed if the internal
158 // asserts are compiled out, statements that are expected to complete
159 // normally always are
160
161 // volatile because the value is modified between setjmp and longjmp
162 // and read afterwards (C11 7.13.2.1)
163 int volatile statement_was_executed = 0;
165 test_failed, YAC_TEST_ABORT_EXPECTED, expected_substr, MPI_COMM_WORLD,
166 statement_was_executed = 1, utest_maybe_abort(1, expected_msg));
167 utest_check(test_failed, "PAR_ALL unhappy path");
168#if YAC_TEST_ABORT_UNHAPPY_PATH_ENABLED
169 if (!statement_was_executed)
170 PUT_ERR("ERROR in PAR_ALL unhappy path: statement was not executed");
171#else
172 if (statement_was_executed)
173 PUT_ERR("ERROR in PAR_ALL unhappy path: statement was executed");
174#endif
175
176 statement_was_executed = 0;
178 test_failed, YAC_TEST_ABORT_NO_CALL, expected_substr, MPI_COMM_WORLD,
179 statement_was_executed = 1, utest_maybe_abort(0, expected_msg));
180 utest_check(test_failed, "PAR_ALL happy path");
181 if (!statement_was_executed)
182 PUT_ERR("ERROR in PAR_ALL happy path: statement was not executed");
183 }
184
185 { // a mismatch has to be detected and reported
186
187 fputs(
188 "NOTE: the following two ERROR lines are part of the test\n", stderr);
189
192 utest_maybe_abort(0, expected_msg));
193#if YAC_TEST_ABORT_UNHAPPY_PATH_ENABLED
194 if (!test_failed)
195 PUT_ERR("ERROR: undetected mismatch (expected abort, got none)");
196#else
197 // the statement is not executed at all, hence there is nothing to detect
198 if (test_failed)
199 PUT_ERR("ERROR: mismatch reported for a skipped statement");
200#endif
201
204 utest_maybe_abort(1, expected_msg));
205 if (!test_failed)
206 PUT_ERR("ERROR: undetected mismatch (expected no abort, got one)");
207 }
208
209 if (yac_get_abort_handler() != initial_handler)
210 PUT_ERR("ERROR: abort handler was not restored");
211
212 MPI_Finalize();
213
214 return TEST_EXIT_CODE;
215}
static char const * expected_substr
static char const * expected_msg
static char const * unexpected_msg
Macros for testing code paths that are expected to abort.
#define YAC_TEST_EXPECT_ABORT_PAR_ALL( test_failed, expected_result, expected_substr, comm,...)
#define YAC_TEST_EXPECT_ABORT_PAR_ANY( test_failed, expected_result, expected_substr, comm,...)
#define YAC_TEST_EXPECT_ABORT_SERIAL( test_failed, expected_result, expected_substr,...)
@ YAC_TEST_ABORT_EXPECTED
abort was called with expected message
@ YAC_TEST_ABORT_UNEXPECTED
abort was called with unexpected message
@ YAC_TEST_ABORT_NO_CALL
abort handler was never invoked
#define PUT_ERR_F(fmt,...)
Definition tests.h:11
#define TEST_EXIT_CODE
Definition tests.h:15
#define PUT_ERR(string)
Definition tests.h:10
yac_abort_func yac_get_abort_handler(void)
void(* yac_abort_func)(MPI_Comm comm, const char *msg, const char *source, int line) __attribute__((noreturn))
Definition yac.h:3587
void yac_abort(MPI_Comm comm, const char *msg, const char *source, int line) __attribute__((noreturn))