c++: constrained lambda error-recovery [PR108972]
[official-gcc.git] / gcc / testsuite / jit.dg / harness.h
blobe423abe9ee1fde23b39caa3d82b0cba00788b68a
1 /*
2 Code shared between multiple testcases.
4 This file contains "main" and support code.
5 Each testcase should implement the following hooks:
7 extern void
8 create_code (gcc_jit_context *ctxt, void * user_data);
10 and, #ifndef TEST_COMPILING_TO_FILE,
12 extern void
13 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result);
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <unistd.h>
19 /* test-threads.c use threads, but dejagnu.h isn't thread-safe; there's a
20 shared "buffer", and the counts of passed/failed etc are globals.
22 The solution is to use macros to rename "pass" and "fail", replacing them
23 with mutex-guarded alternatives. */
24 #ifdef MAKE_DEJAGNU_H_THREADSAFE
25 #define pass dejagnu_pass
26 #define fail dejagnu_fail
27 #define note dejagnu_note
28 #endif
30 #include "jit-dejagnu.h"
32 #ifdef MAKE_DEJAGNU_H_THREADSAFE
33 #undef pass
34 #undef fail
35 #undef note
36 #endif
38 static char test[1024];
40 #define CHECK_NON_NULL(PTR) \
41 do { \
42 if ((PTR) != NULL) \
43 { \
44 pass ("%s: %s: %s is non-null", \
45 test, __func__, #PTR); \
46 } \
47 else \
48 { \
49 fail ("%s: %s: %s is NULL", \
50 test, __func__, #PTR); \
51 abort (); \
52 } \
53 } while (0)
55 #define CHECK_VALUE(ACTUAL, EXPECTED) \
56 do { \
57 if ((ACTUAL) == (EXPECTED)) \
58 { \
59 pass ("%s: %s: actual: %s == expected: %s", \
60 test, __func__, #ACTUAL, #EXPECTED); \
61 } \
62 else \
63 { \
64 fail ("%s: %s: actual: %s != expected: %s", \
65 test, __func__, #ACTUAL, #EXPECTED); \
66 fprintf (stderr, "incorrect value\n"); \
67 abort (); \
68 } \
69 } while (0)
71 #define CHECK_VECTOR_VALUE(LEN, ACTUAL, EXPECTED) \
72 do { \
73 for (int __check_vector_it = 0; __check_vector_it < LEN; ++__check_vector_it) { \
74 if ((ACTUAL)[__check_vector_it] != (EXPECTED)[__check_vector_it]) { \
75 fail ("%s: %s: actual: %s != expected: %s (position %d)", \
76 test, __func__, #ACTUAL, #EXPECTED, __check_vector_it); \
77 fprintf (stderr, "incorrect value\n"); \
78 abort (); \
79 } \
80 } \
81 pass ("%s: %s: actual: %s == expected: %s", \
82 test, __func__, #ACTUAL, #EXPECTED); \
83 } while (0)
86 #define CHECK_DOUBLE_VALUE(ACTUAL, EXPECTED) \
87 do { \
88 double expected = (EXPECTED); \
89 double actual = (ACTUAL); \
90 if (abs (actual - expected) < 0.00001) \
91 { \
92 pass ("%s: %s: actual: %s == expected: %s", \
93 __func__, test, #ACTUAL, #EXPECTED); \
94 } \
95 else \
96 { \
97 fail ("%s: %s: actual: %s != expected: %s", \
98 __func__, test, #ACTUAL, #EXPECTED); \
99 fprintf (stderr, "incorrect value: %f\n", actual); \
100 abort (); \
102 } while (0)
104 #define CHECK_STRING_VALUE(ACTUAL, EXPECTED) \
105 check_string_value (__func__, (ACTUAL), (EXPECTED));
107 #define CHECK_STRING_STARTS_WITH(ACTUAL, EXPECTED_PREFIX) \
108 check_string_starts_with (__func__, (ACTUAL), (EXPECTED_PREFIX));
110 #define CHECK_STRING_CONTAINS(ACTUAL, EXPECTED_SUBSTRING) \
111 check_string_contains (__func__, #ACTUAL, (ACTUAL), (EXPECTED_SUBSTRING));
113 #define CHECK(COND) \
114 do { \
115 if (COND) \
117 pass ("%s: %s: %s", test, __func__, #COND); \
119 else \
121 fail ("%s: %s: %s", test, __func__, #COND); \
122 abort (); \
124 } while (0)
126 #define CHECK_NO_ERRORS(CTXT) \
127 do { \
128 const char *err = gcc_jit_context_get_first_error (CTXT); \
129 if (err) \
130 fail ("%s: %s: error unexpectedly occurred: %s", test, __func__, err); \
131 else \
132 pass ("%s: %s: no errors occurred", test, __func__); \
133 } while (0)
135 /* Hooks that testcases should provide. */
136 extern void
137 create_code (gcc_jit_context *ctxt, void * user_data);
139 #ifndef TEST_COMPILING_TO_FILE
140 extern void
141 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result);
142 #endif
144 extern void check_string_value (const char *funcname,
145 const char *actual, const char *expected);
147 extern void
148 check_string_starts_with (const char *funcname,
149 const char *actual,
150 const char *expected_prefix);
152 extern void
153 check_string_contains (const char *funcname,
154 const char *name,
155 const char *actual,
156 const char *expected_substring);
158 /* Implement framework needed for turning the testcase hooks into an
159 executable. test-combination.c and test-threads.c each combine multiple
160 testcases into larger testcases, so we have COMBINED_TEST as a way of
161 temporarily turning off this part of harness.h. */
162 #ifndef COMBINED_TEST
164 void check_string_value (const char *funcname,
165 const char *actual, const char *expected)
167 if (actual && !expected)
169 fail ("%s: %s: actual: \"%s\" != expected: NULL",
170 funcname, test, actual);
171 fprintf (stderr, "incorrect value\n");
172 abort ();
174 if (expected && !actual)
176 fail ("%s: %s: actual: NULL != expected: \"%s\"",
177 funcname, test, expected);
178 fprintf (stderr, "incorrect value\n");
179 abort ();
181 if (actual && expected)
183 if (strcmp (actual, expected))
185 fail ("%s: %s: actual: \"%s\" != expected: \"%s\"",
186 test, funcname, actual, expected);
187 fprintf (stderr, "incorrect valuen");
188 abort ();
190 pass ("%s: %s: actual: \"%s\" == expected: \"%s\"",
191 test, funcname, actual, expected);
193 else
194 pass ("%s: actual: NULL == expected: NULL");
197 void
198 check_string_starts_with (const char *funcname,
199 const char *actual,
200 const char *expected_prefix)
202 if (!actual)
204 fail ("%s: %s: actual: NULL != expected prefix: \"%s\"",
205 test, funcname, expected_prefix);
206 fprintf (stderr, "incorrect value\n");
207 abort ();
210 if (strncmp (actual, expected_prefix, strlen (expected_prefix)))
212 fail ("%s: %s: actual: \"%s\" did not begin with expected prefix: \"%s\"",
213 test, funcname, actual, expected_prefix);
214 fprintf (stderr, "incorrect value\n");
215 abort ();
218 pass ("%s: actual: \"%s\" begins with expected prefix: \"%s\"",
219 test, actual, expected_prefix);
222 void
223 check_string_contains (const char *funcname,
224 const char *name,
225 const char *actual,
226 const char *expected_substring)
228 if (!actual)
230 fail ("%s: %s, %s: actual: NULL does not contain expected substring: \"%s\"",
231 test, funcname, name, expected_substring);
232 fprintf (stderr, "incorrect value\n");
233 abort ();
236 if (!strstr (actual, expected_substring))
238 fail ("%s: %s: %s: actual: \"%s\" did not contain expected substring: \"%s\"",
239 test, funcname, name, actual, expected_substring);
240 fprintf (stderr, "incorrect value\n");
241 abort ();
244 pass ("%s: %s: %s: found substring: \"%s\"",
245 test, funcname, name, expected_substring);
248 #ifndef TEST_ESCHEWS_SET_OPTIONS
249 static void set_options (gcc_jit_context *ctxt, const char *argv0)
251 /* Set up options. */
252 gcc_jit_context_set_str_option (
253 ctxt,
254 GCC_JIT_STR_OPTION_PROGNAME,
255 argv0);
256 gcc_jit_context_set_int_option (
257 ctxt,
258 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
260 gcc_jit_context_set_bool_option (
261 ctxt,
262 GCC_JIT_BOOL_OPTION_DEBUGINFO,
264 gcc_jit_context_set_bool_option (
265 ctxt,
266 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE,
268 gcc_jit_context_set_bool_option (
269 ctxt,
270 GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
272 gcc_jit_context_set_bool_option (
273 ctxt,
274 GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
276 gcc_jit_context_set_bool_option (
277 ctxt,
278 GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
280 /* Make it easier to compare error messages by disabling colorization,
281 rather then have them be affected by whether stderr is going to a tty. */
282 gcc_jit_context_add_command_line_option
283 (ctxt, "-fdiagnostics-color=never");
285 #endif /* #ifndef TEST_ESCHEWS_SET_OPTIONS */
287 /* Concatenate two strings. The result must be released using "free". */
289 char *
290 concat_strings (const char *prefix, const char *suffix)
292 char *result = (char *)malloc (strlen (prefix) + strlen (suffix) + 1);
293 if (!result)
295 fail ("malloc failure");
296 return NULL;
298 strcpy (result, prefix);
299 strcpy (result + strlen (prefix), suffix);
300 result[strlen (prefix) + strlen (suffix)] = '\0';
301 return result;
304 #ifndef TEST_ESCHEWS_TEST_JIT
305 /* Set up logging to a logfile of the form "test-FOO.exe.log.txt".
307 For example,
308 SRCDIR/gcc/testsuite/jit.dg/test-hello-world.c
309 is built as:
310 BUILDDIR/gcc/testsuite/jit/test-hello-world.c.exe
311 and is logged to
312 BUILDDIR/gcc/testsuite/jit/test-hello-world.c.exe.log.txt
314 The logfile must be closed by the caller.
316 Note that not every testcase enables logging. */
317 static FILE *
318 set_up_logging (gcc_jit_context *ctxt, const char *argv0)
320 const char *logfile_name_suffix = ".log.txt";
321 char *logfile_name = NULL;
322 FILE *logfile = NULL;
324 /* Build a logfile name of the form "test-FOO.exe.log.txt". */
325 logfile_name = concat_strings (argv0, logfile_name_suffix);
326 if (!logfile_name)
327 return NULL;
328 logfile = fopen (logfile_name, "w");
329 CHECK_NON_NULL (logfile);
330 free (logfile_name);
332 if (logfile)
333 gcc_jit_context_set_logfile (ctxt, logfile, 0, 0);
335 return logfile;
338 /* Exercise the API entrypoint:
339 gcc_jit_context_dump_reproducer_to_file
340 by calling it on the context, using the path expected by jit.exp. */
341 static void
342 dump_reproducer (gcc_jit_context *ctxt, const char *argv0)
344 char *reproducer_name;
345 reproducer_name = concat_strings (argv0, ".reproducer.c");
346 if (!reproducer_name)
347 return;
348 note ("%s: writing reproducer to %s", test, reproducer_name);
349 gcc_jit_context_dump_reproducer_to_file (ctxt, reproducer_name);
350 free (reproducer_name);
353 /* Run one iteration of the test. */
354 static void
355 test_jit (const char *argv0, void *user_data)
357 gcc_jit_context *ctxt;
358 FILE *logfile;
359 #ifndef TEST_COMPILING_TO_FILE
360 gcc_jit_result *result;
361 #endif
363 #ifdef TEST_COMPILING_TO_FILE
364 unlink (OUTPUT_FILENAME);
365 #endif
367 ctxt = gcc_jit_context_acquire ();
368 if (!ctxt)
370 fail ("gcc_jit_context_acquire failed");
371 return;
374 logfile = set_up_logging (ctxt, argv0);
376 set_options (ctxt, argv0);
378 create_code (ctxt, user_data);
380 dump_reproducer (ctxt, argv0);
382 #ifdef TEST_COMPILING_TO_FILE
383 gcc_jit_context_compile_to_file (ctxt,
384 (OUTPUT_KIND),
385 (OUTPUT_FILENAME));
386 CHECK_NO_ERRORS (ctxt);
387 #else /* #ifdef TEST_COMPILING_TO_FILE */
388 /* This actually calls into GCC and runs the build, all
389 in a mutex for now. */
390 result = gcc_jit_context_compile (ctxt);
392 verify_code (ctxt, result);
393 #endif
395 gcc_jit_context_release (ctxt);
397 #ifndef TEST_COMPILING_TO_FILE
398 /* Once we're done with the code, this unloads the built .so file: */
399 gcc_jit_result_release (result);
400 #endif
402 if (logfile)
403 fclose (logfile);
405 #endif /* #ifndef TEST_ESCHEWS_TEST_JIT */
407 /* We want to prefix all unit test results with the test, but dejagnu.exp's
408 host_execute appears to get confused by the leading "./" of argv0,
409 leading to all tests simply reporting as a single period character ".".
411 Hence strip out the final component of the path to the program name,
412 so that we can use that in unittest reports. */
413 const char*
414 extract_progname (const char *argv0)
416 const char *p;
418 p = argv0 + strlen (argv0);
419 while (p != argv0 && p[-1] != '/')
420 --p;
421 return p;
424 #ifndef TEST_PROVIDES_MAIN
426 main (int argc, char **argv)
428 int i;
430 for (i = 1; i <= 5; i++)
432 snprintf (test, sizeof (test),
433 "%s iteration %d of %d",
434 extract_progname (argv[0]),
435 i, 5);
437 //printf ("ITERATION %d\n", i);
438 test_jit (argv[0], NULL);
439 //printf ("\n");
442 totals ();
444 return 0;
446 #endif /* #ifndef TEST_PROVIDES_MAIN */
448 #endif /* #ifndef COMBINED_TEST */