harness.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. Code shared between multiple testcases.
  3. This file contains "main" and support code.
  4. Each testcase should implement the following hooks:
  5. extern void
  6. create_code (gcc_jit_context *ctxt, void * user_data);
  7. and, #ifndef TEST_COMPILING_TO_FILE,
  8. extern void
  9. verify_code (gcc_jit_context *ctxt, gcc_jit_result *result);
  10. */
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <unistd.h>
  14. /* test-threads.c use threads, but dejagnu.h isn't thread-safe; there's a
  15. shared "buffer", and the counts of passed/failed etc are globals.
  16. The solution is to use macros to rename "pass" and "fail", replacing them
  17. with mutex-guarded alternatives. */
  18. #ifdef MAKE_DEJAGNU_H_THREADSAFE
  19. #define pass dejagnu_pass
  20. #define fail dejagnu_fail
  21. #define note dejagnu_note
  22. #endif
  23. #include <dejagnu.h>
  24. #ifdef MAKE_DEJAGNU_H_THREADSAFE
  25. #undef pass
  26. #undef fail
  27. #undef note
  28. #endif
  29. static char test[1024];
  30. #define CHECK_NON_NULL(PTR) \
  31. do { \
  32. if ((PTR) != NULL) \
  33. { \
  34. pass ("%s: %s: %s is non-null", \
  35. test, __func__, #PTR); \
  36. } \
  37. else \
  38. { \
  39. fail ("%s: %s: %s is NULL", \
  40. test, __func__, #PTR); \
  41. abort (); \
  42. } \
  43. } while (0)
  44. #define CHECK_VALUE(ACTUAL, EXPECTED) \
  45. do { \
  46. if ((ACTUAL) == (EXPECTED)) \
  47. { \
  48. pass ("%s: %s: actual: %s == expected: %s", \
  49. test, __func__, #ACTUAL, #EXPECTED); \
  50. } \
  51. else \
  52. { \
  53. fail ("%s: %s: actual: %s != expected: %s", \
  54. test, __func__, #ACTUAL, #EXPECTED); \
  55. fprintf (stderr, "incorrect value\n"); \
  56. abort (); \
  57. } \
  58. } while (0)
  59. #define CHECK_DOUBLE_VALUE(ACTUAL, EXPECTED) \
  60. do { \
  61. double expected = (EXPECTED); \
  62. double actual = (ACTUAL); \
  63. if (abs (actual - expected) < 0.00001) \
  64. { \
  65. pass ("%s: %s: actual: %s == expected: %s", \
  66. __func__, test, #ACTUAL, #EXPECTED); \
  67. } \
  68. else \
  69. { \
  70. fail ("%s: %s: actual: %s != expected: %s", \
  71. __func__, test, #ACTUAL, #EXPECTED); \
  72. fprintf (stderr, "incorrect value: %f\n", actual); \
  73. abort (); \
  74. } \
  75. } while (0)
  76. #define CHECK_STRING_VALUE(ACTUAL, EXPECTED) \
  77. check_string_value (__func__, (ACTUAL), (EXPECTED));
  78. #define CHECK_STRING_STARTS_WITH(ACTUAL, EXPECTED_PREFIX) \
  79. check_string_starts_with (__func__, (ACTUAL), (EXPECTED_PREFIX));
  80. #define CHECK_STRING_CONTAINS(ACTUAL, EXPECTED_SUBSTRING) \
  81. check_string_contains (__func__, #ACTUAL, (ACTUAL), (EXPECTED_SUBSTRING));
  82. #define CHECK(COND) \
  83. do { \
  84. if (COND) \
  85. { \
  86. pass ("%s: %s: %s", test, __func__, #COND); \
  87. } \
  88. else \
  89. { \
  90. fail ("%s: %s: %s", test, __func__, #COND); \
  91. abort (); \
  92. } \
  93. } while (0)
  94. #define CHECK_NO_ERRORS(CTXT) \
  95. do { \
  96. const char *err = gcc_jit_context_get_first_error (CTXT); \
  97. if (err) \
  98. fail ("%s: %s: error unexpectedly occurred: %s", test, __func__, err); \
  99. else \
  100. pass ("%s: %s: no errors occurred", test, __func__); \
  101. } while (0)
  102. /* Hooks that testcases should provide. */
  103. extern void
  104. create_code (gcc_jit_context *ctxt, void * user_data);
  105. #ifndef TEST_COMPILING_TO_FILE
  106. extern void
  107. verify_code (gcc_jit_context *ctxt, gcc_jit_result *result);
  108. #endif
  109. extern void check_string_value (const char *funcname,
  110. const char *actual, const char *expected);
  111. extern void
  112. check_string_starts_with (const char *funcname,
  113. const char *actual,
  114. const char *expected_prefix);
  115. extern void
  116. check_string_contains (const char *funcname,
  117. const char *name,
  118. const char *actual,
  119. const char *expected_substring);
  120. /* Implement framework needed for turning the testcase hooks into an
  121. executable. test-combination.c and test-threads.c each combine multiple
  122. testcases into larger testcases, so we have COMBINED_TEST as a way of
  123. temporarily turning off this part of harness.h. */
  124. #ifndef COMBINED_TEST
  125. void check_string_value (const char *funcname,
  126. const char *actual, const char *expected)
  127. {
  128. if (actual && !expected)
  129. {
  130. fail ("%s: %s: actual: \"%s\" != expected: NULL",
  131. funcname, test, actual);
  132. fprintf (stderr, "incorrect value\n");
  133. abort ();
  134. }
  135. if (expected && !actual)
  136. {
  137. fail ("%s: %s: actual: NULL != expected: \"%s\"",
  138. funcname, test, expected);
  139. fprintf (stderr, "incorrect value\n");
  140. abort ();
  141. }
  142. if (actual && expected)
  143. {
  144. if (strcmp (actual, expected))
  145. {
  146. fail ("%s: %s: actual: \"%s\" != expected: \"%s\"",
  147. test, funcname, actual, expected);
  148. fprintf (stderr, "incorrect valuen");
  149. abort ();
  150. }
  151. pass ("%s: %s: actual: \"%s\" == expected: \"%s\"",
  152. test, funcname, actual, expected);
  153. }
  154. else
  155. pass ("%s: actual: NULL == expected: NULL");
  156. }
  157. void
  158. check_string_starts_with (const char *funcname,
  159. const char *actual,
  160. const char *expected_prefix)
  161. {
  162. if (!actual)
  163. {
  164. fail ("%s: %s: actual: NULL != expected prefix: \"%s\"",
  165. test, funcname, expected_prefix);
  166. fprintf (stderr, "incorrect value\n");
  167. abort ();
  168. }
  169. if (strncmp (actual, expected_prefix, strlen (expected_prefix)))
  170. {
  171. fail ("%s: %s: actual: \"%s\" did not begin with expected prefix: \"%s\"",
  172. test, funcname, actual, expected_prefix);
  173. fprintf (stderr, "incorrect value\n");
  174. abort ();
  175. }
  176. pass ("%s: actual: \"%s\" begins with expected prefix: \"%s\"",
  177. test, actual, expected_prefix);
  178. }
  179. void
  180. check_string_contains (const char *funcname,
  181. const char *name,
  182. const char *actual,
  183. const char *expected_substring)
  184. {
  185. if (!actual)
  186. {
  187. fail ("%s: %s, %s: actual: NULL does not contain expected substring: \"%s\"",
  188. test, funcname, name, expected_substring);
  189. fprintf (stderr, "incorrect value\n");
  190. abort ();
  191. }
  192. if (!strstr (actual, expected_substring))
  193. {
  194. fail ("%s: %s: %s: actual: \"%s\" did not contain expected substring: \"%s\"",
  195. test, funcname, name, actual, expected_substring);
  196. fprintf (stderr, "incorrect value\n");
  197. abort ();
  198. }
  199. pass ("%s: %s: %s: found substring: \"%s\"",
  200. test, funcname, name, expected_substring);
  201. }
  202. #ifndef TEST_ESCHEWS_SET_OPTIONS
  203. static void set_options (gcc_jit_context *ctxt, const char *argv0)
  204. {
  205. /* Set up options. */
  206. gcc_jit_context_set_str_option (
  207. ctxt,
  208. GCC_JIT_STR_OPTION_PROGNAME,
  209. argv0);
  210. gcc_jit_context_set_int_option (
  211. ctxt,
  212. GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
  213. 3);
  214. gcc_jit_context_set_bool_option (
  215. ctxt,
  216. GCC_JIT_BOOL_OPTION_DEBUGINFO,
  217. 1);
  218. gcc_jit_context_set_bool_option (
  219. ctxt,
  220. GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE,
  221. 0);
  222. gcc_jit_context_set_bool_option (
  223. ctxt,
  224. GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
  225. 0);
  226. gcc_jit_context_set_bool_option (
  227. ctxt,
  228. GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
  229. 1);
  230. gcc_jit_context_set_bool_option (
  231. ctxt,
  232. GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
  233. 0);
  234. }
  235. #endif /* #ifndef TEST_ESCHEWS_SET_OPTIONS */
  236. /* Concatenate two strings. The result must be released using "free". */
  237. char *
  238. concat_strings (const char *prefix, const char *suffix)
  239. {
  240. char *result = (char *)malloc (strlen (prefix) + strlen (suffix) + 1);
  241. if (!result)
  242. {
  243. fail ("malloc failure");
  244. return NULL;
  245. }
  246. strcpy (result, prefix);
  247. strcpy (result + strlen (prefix), suffix);
  248. result[strlen (prefix) + strlen (suffix)] = '\0';
  249. return result;
  250. }
  251. #ifndef TEST_ESCHEWS_TEST_JIT
  252. /* Set up logging to a logfile of the form "test-FOO.exe.log.txt".
  253. For example,
  254. SRCDIR/gcc/testsuite/jit.dg/test-hello-world.c
  255. is built as:
  256. BUILDDIR/gcc/testsuite/jit/test-hello-world.c.exe
  257. and is logged to
  258. BUILDDIR/gcc/testsuite/jit/test-hello-world.c.exe.log.txt
  259. The logfile must be closed by the caller.
  260. Note that not every testcase enables logging. */
  261. static FILE *
  262. set_up_logging (gcc_jit_context *ctxt, const char *argv0)
  263. {
  264. const char *logfile_name_suffix = ".log.txt";
  265. char *logfile_name = NULL;
  266. FILE *logfile = NULL;
  267. /* Build a logfile name of the form "test-FOO.exe.log.txt". */
  268. logfile_name = concat_strings (argv0, logfile_name_suffix);
  269. if (!logfile_name)
  270. return NULL;
  271. logfile = fopen (logfile_name, "w");
  272. CHECK_NON_NULL (logfile);
  273. free (logfile_name);
  274. if (logfile)
  275. gcc_jit_context_set_logfile (ctxt, logfile, 0, 0);
  276. return logfile;
  277. }
  278. /* Exercise the API entrypoint:
  279. gcc_jit_context_dump_reproducer_to_file
  280. by calling it on the context, using the path expected by jit.exp. */
  281. static void
  282. dump_reproducer (gcc_jit_context *ctxt, const char *argv0)
  283. {
  284. char *reproducer_name;
  285. reproducer_name = concat_strings (argv0, ".reproducer.c");
  286. if (!reproducer_name)
  287. return;
  288. note ("%s: writing reproducer to %s", test, reproducer_name);
  289. gcc_jit_context_dump_reproducer_to_file (ctxt, reproducer_name);
  290. free (reproducer_name);
  291. }
  292. /* Run one iteration of the test. */
  293. static void
  294. test_jit (const char *argv0, void *user_data)
  295. {
  296. gcc_jit_context *ctxt;
  297. FILE *logfile;
  298. #ifndef TEST_COMPILING_TO_FILE
  299. gcc_jit_result *result;
  300. #endif
  301. #ifdef TEST_COMPILING_TO_FILE
  302. unlink (OUTPUT_FILENAME);
  303. #endif
  304. ctxt = gcc_jit_context_acquire ();
  305. if (!ctxt)
  306. {
  307. fail ("gcc_jit_context_acquire failed");
  308. return;
  309. }
  310. logfile = set_up_logging (ctxt, argv0);
  311. set_options (ctxt, argv0);
  312. create_code (ctxt, user_data);
  313. dump_reproducer (ctxt, argv0);
  314. #ifdef TEST_COMPILING_TO_FILE
  315. gcc_jit_context_compile_to_file (ctxt,
  316. (OUTPUT_KIND),
  317. (OUTPUT_FILENAME));
  318. CHECK_NO_ERRORS (ctxt);
  319. #else /* #ifdef TEST_COMPILING_TO_FILE */
  320. /* This actually calls into GCC and runs the build, all
  321. in a mutex for now. */
  322. result = gcc_jit_context_compile (ctxt);
  323. verify_code (ctxt, result);
  324. #endif
  325. gcc_jit_context_release (ctxt);
  326. #ifndef TEST_COMPILING_TO_FILE
  327. /* Once we're done with the code, this unloads the built .so file: */
  328. gcc_jit_result_release (result);
  329. #endif
  330. if (logfile)
  331. fclose (logfile);
  332. }
  333. #endif /* #ifndef TEST_ESCHEWS_TEST_JIT */
  334. /* We want to prefix all unit test results with the test, but dejagnu.exp's
  335. host_execute appears to get confused by the leading "./" of argv0,
  336. leading to all tests simply reporting as a single period character ".".
  337. Hence strip out the final component of the path to the program name,
  338. so that we can use that in unittest reports. */
  339. const char*
  340. extract_progname (const char *argv0)
  341. {
  342. const char *p;
  343. p = argv0 + strlen (argv0);
  344. while (p != argv0 && p[-1] != '/')
  345. --p;
  346. return p;
  347. }
  348. #ifndef TEST_PROVIDES_MAIN
  349. int
  350. main (int argc, char **argv)
  351. {
  352. int i;
  353. for (i = 1; i <= 5; i++)
  354. {
  355. snprintf (test, sizeof (test),
  356. "%s iteration %d of %d",
  357. extract_progname (argv[0]),
  358. i, 5);
  359. //printf ("ITERATION %d\n", i);
  360. test_jit (argv[0], NULL);
  361. //printf ("\n");
  362. }
  363. totals ();
  364. return 0;
  365. }
  366. #endif /* #ifndef TEST_PROVIDES_MAIN */
  367. #endif /* #ifndef COMBINED_TEST */