checkmk 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. #! /usr/bin/gawk -f
  2. # checkmk/checkmk. Generated from checkmk.in by configure.
  3. # checkmk - translate more concise versions of test suite specifications
  4. # into C programs suitable for use with the Check unit test
  5. # framework.
  6. # -- LICENSE --
  7. #
  8. # Written by Micah Cowan <micah@cowan.name>
  9. # Copyright (c) 2006, 2010 Micah Cowan
  10. #
  11. # Redistribution of this program in any form, with or without
  12. # modifications, is permitted, provided that the above copyright is
  13. # retained in distributions of this program in source form.
  14. #
  15. # (This is a free, non-copyleft license compatible with pretty much any
  16. # other free or proprietary license, including the GPL. It's essentially
  17. # a scaled-down version of the "modified" BSD license.)
  18. BEGIN {
  19. progname="checkmk";
  20. is_stdin=0;
  21. outfname="/dev/stdout";
  22. # Tokens
  23. pp_ws = "[ \t\f\v\r\n]+";
  24. pp_ws_op = "[ \t\f\v\r\n]*";
  25. pp_digit = "[0-9]+"
  26. pp_prefix = pp_ws_op "#" pp_ws_op;
  27. pp_sep = "[ \t\f\v\r\n]+";
  28. pp_name = ".+";
  29. pp_hex_quad = "[A-F0-9a-f][A-F0-9a-f][A-F0-9a-f][A-F0-9a-f]"
  30. pp_ucn = "\\\\(u" pp_hex_quad "|U" pp_hex_quad pp_hex_quad ")";
  31. pp_test_name = "([A-Za-z_]|" pp_ucn ")([A-Za-z0-9_]|" pp_ucn ")*";
  32. pp_tag = "([Ss][Uu][Ii][Tt][Ee]|[Tt][Cc][Aa][Ss][Ee])";
  33. pp_test_tag = "[Tt][Ee][Ss][Tt]";
  34. pp_main_pre_tag = "[Mm][Aa][Ii][Nn]-[Pp][Rr][Ee]";
  35. pp_main_post_tag = "[Mm][Aa][Ii][Nn]-[Pp][Oo][Ss][Tt]";
  36. # Tests with arguments
  37. pp_test_exit_tag = "[Tt][Ee][Ss][Tt]-[Ee][Xx][Ii][Tt]" pp_ws_op "[(]" \
  38. pp_ws_op "[+-]?" pp_ws_op pp_digit pp_ws_op "[)]";
  39. pp_test_signal_tag = "[Tt][Ee][Ss][Tt]-[Ss][Ii][Gg][Nn][Aa][Ll]" pp_ws_op \
  40. "[(]" pp_ws_op "[+-]?" pp_ws_op pp_digit pp_ws_op "[)]";
  41. pp_test_loop_tag = "[Tt][Ee][Ss][Tt]-[Ll][Oo][Oo][Pp]" pp_ws_op "[(]" \
  42. pp_ws_op "[+-]?" pp_ws_op pp_digit pp_ws_op "[,]" pp_ws_op \
  43. "[+-]?" pp_ws_op pp_digit pp_ws_op "[)]";
  44. pp_test_loop_exit_tag = "[Tt][Ee][Ss][Tt]-[Ll][Oo][Oo][Pp]-[Ee][Xx][Ii][Tt]" \
  45. pp_ws_op "[(]" pp_ws_op "[+-]?" pp_ws_op pp_digit pp_ws_op \
  46. "[,]" pp_ws_op "[+-]?" pp_ws_op pp_digit pp_ws_op "[,]" \
  47. pp_ws_op "[+-]?" pp_ws_op pp_digit pp_ws_op "[)]";
  48. pp_test_loop_signal_tag = "[Tt][Ee][Ss][Tt]-[Ll][Oo][Oo][Pp]-[Ss][Ii][Gg]" \
  49. "[Nn][Aa][Ll]" pp_ws_op "[(]" pp_ws_op "[+-]?" pp_ws_op pp_digit \
  50. pp_ws_op "[,]" pp_ws_op "[+-]?" pp_ws_op pp_digit pp_ws_op \
  51. "[,]" pp_ws_op "[+-]?" pp_ws_op pp_digit pp_ws_op "[)]";
  52. pp_suite_or_tcase_line = "^" pp_prefix pp_tag pp_ws pp_name "$";
  53. pp_test_line_prefix = "^" pp_prefix pp_test_tag pp_ws;
  54. pp_test_exit_line_prefix = "^" pp_prefix pp_test_exit_tag pp_ws;
  55. pp_test_signal_line_prefix = "^" pp_prefix pp_test_signal_tag pp_ws;
  56. pp_test_loop_line_prefix = "^" pp_prefix pp_test_loop_tag pp_ws;
  57. pp_test_loop_exit_line_prefix = "^" pp_prefix pp_test_loop_exit_tag pp_ws;
  58. pp_test_loop_signal_line_prefix = "^" pp_prefix pp_test_loop_signal_tag pp_ws;
  59. pp_test_line = pp_test_line_prefix pp_name pp_ws_op "$";
  60. pp_test_exit_line = pp_test_exit_line_prefix pp_name pp_ws_op "$";
  61. pp_test_signal_line = pp_test_signal_line_prefix pp_name pp_ws_op "$";
  62. pp_test_loop_line = pp_test_loop_line_prefix pp_name pp_ws_op "$";
  63. pp_test_loop_exit_line = pp_test_loop_exit_line_prefix pp_name pp_ws_op "$";
  64. pp_test_loop_signal_line = pp_test_loop_signal_line_prefix pp_name pp_ws_op "$";
  65. pp_main_pre_line = "^" pp_prefix pp_main_pre_tag pp_ws_op "$";
  66. pp_main_post_line = "^" pp_prefix pp_main_post_tag pp_ws_op "$";
  67. # Global vars
  68. in_test = needs_line_decl = 0;
  69. cur_suite = cur_tcase = "Core";
  70. cur_test = "";
  71. exit_okay = start = 1;
  72. num_cur_tcases = num_cur_tests = 0;
  73. test_type = num_tests = 0;
  74. arg1 = 0;
  75. arg2 = 1;
  76. arg3 = 2;
  77. test_name = 0;
  78. test_type_flag = 1;
  79. }
  80. # Run on the first line of the input file.
  81. start {
  82. print_boilerplate();
  83. start = 0;
  84. }
  85. # (Executed every line:)
  86. {
  87. print_line = 1;
  88. }
  89. $0 ~ pp_suite_or_tcase_line {
  90. if (in_main())
  91. in_main_error();
  92. # Skip to the start of the tag ("suite" or "tcase").
  93. match($0, pp_prefix);
  94. rol = substr($0, RLENGTH+1);
  95. # Save away the tag.
  96. match(rol, "^" pp_tag);
  97. tag = substr(rol, 1, RLENGTH);
  98. # Advance past the ws following tag.
  99. rol = substr(rol, RLENGTH+1);
  100. match(rol, pp_ws);
  101. rol = substr(rol, RLENGTH+1);
  102. # The suite or tcase name is the rest of the line, minus any
  103. # trailing ws.
  104. if (match(rol, pp_ws "$")) {
  105. name = substr(rol, 1, RSTART-1);
  106. } else {
  107. name = rol;
  108. }
  109. if (tolower(tag) == "suite") {
  110. # Does this suite already exist?
  111. if ((name, 0) in suite_tcase_map) {
  112. error_with_line("Suite \"" name "\" already exists.");
  113. }
  114. cur_suite = name;
  115. num_cur_tcases = 0;
  116. }
  117. else if ((name, 0, 0) in tcase_test_map) {
  118. error_with_line("Test Case \"" name "\" already exists.");
  119. }
  120. cur_tcase = name;
  121. num_cur_tests = 0;
  122. finish_test();
  123. print_line = 0;
  124. if (!clean_mode)
  125. needs_line_decl = 1;
  126. }
  127. $0 ~ pp_test_line {
  128. # Pre checks
  129. test_pre();
  130. # Get the test name
  131. match($0, pp_test_line_prefix)
  132. cur_test = substr($0, RLENGTH+1);
  133. # Remove trailing ws.
  134. sub(pp_ws_op "$", "", cur_test);
  135. # Check for duplicate tests / cases and valid names
  136. duplicate_check();
  137. # Boilerplate printing code
  138. test_post();
  139. # Set type before calling register
  140. test_type = 0;
  141. register_test();
  142. print_line = 0;
  143. in_test = 1;
  144. }
  145. $0 ~ pp_test_loop_line {
  146. test_pre();
  147. match($0, pp_test_loop_line_prefix)
  148. cur_test = substr($0, RLENGTH+1);
  149. sub(pp_ws_op "$", "", cur_test);
  150. duplicate_check();
  151. # Split the line into an array to extract the arguments
  152. split($0, arr, pp_ws_op "[(),]" pp_ws_op);
  153. # Eliminate possible whitespace between sign and numbers
  154. gsub(pp_ws_op, "", arr[2]);
  155. gsub(pp_ws_op, "", arr[3]);
  156. test_post();
  157. test_type = 1;
  158. register_test();
  159. print_line = 0;
  160. in_test = 1;
  161. }
  162. $0 ~ pp_test_exit_line {
  163. test_pre();
  164. match($0, pp_test_exit_line_prefix)
  165. cur_test = substr($0, RLENGTH+1);
  166. sub(pp_ws_op "$", "", cur_test);
  167. duplicate_check();
  168. split($0, arr, pp_ws_op "[(),]" pp_ws_op);
  169. gsub(pp_ws_op, "", arr[2]);
  170. test_post();
  171. test_type = 2;
  172. register_test();
  173. print_line = 0;
  174. in_test = 1;
  175. }
  176. $0 ~ pp_test_signal_line {
  177. test_pre();
  178. match($0, pp_test_signal_line_prefix)
  179. cur_test = substr($0, RLENGTH+1);
  180. sub(pp_ws_op "$", "", cur_test);
  181. duplicate_check();
  182. split($0, arr, pp_ws_op "[(),]" pp_ws_op);
  183. gsub(pp_ws_op, "", arr[2]);
  184. test_post();
  185. test_type = 3;
  186. register_test();
  187. print_line = 0;
  188. in_test = 1;
  189. }
  190. $0 ~ pp_test_loop_exit_line {
  191. test_pre();
  192. match($0, pp_test_loop_exit_line_prefix)
  193. cur_test = substr($0, RLENGTH+1);
  194. sub(pp_ws_op "$", "", cur_test);
  195. duplicate_check();
  196. split($0, arr, pp_ws_op "[(),]" pp_ws_op);
  197. gsub(pp_ws_op, "", arr[2]);
  198. gsub(pp_ws_op, "", arr[3]);
  199. gsub(pp_ws_op, "", arr[4]);
  200. test_post();
  201. test_type = 4;
  202. register_test();
  203. print_line = 0;
  204. in_test = 1;
  205. }
  206. $0 ~ pp_test_loop_signal_line {
  207. test_pre();
  208. match($0, pp_test_loop_signal_line_prefix)
  209. cur_test = substr($0, RLENGTH+1);
  210. sub(pp_ws_op "$", "", cur_test);
  211. duplicate_check();
  212. split($0, arr, pp_ws_op "[(),]" pp_ws_op);
  213. gsub(pp_ws_op, "", arr[2]);
  214. gsub(pp_ws_op, "", arr[3]);
  215. gsub(pp_ws_op, "", arr[4]);
  216. test_post();
  217. test_type = 5;
  218. register_test();
  219. print_line = 0;
  220. in_test = 1;
  221. }
  222. $0 ~ pp_main_pre_line {
  223. main_pre();
  224. print "";
  225. print " /* User-specified pre-run code */";
  226. if (!clean_mode)
  227. needs_line_decl = 1;
  228. print_line = 0;
  229. }
  230. $0 ~ pp_main_post_line {
  231. main_post();
  232. print "";
  233. print " /* User-specified post-run code */";
  234. if (!clean_mode)
  235. needs_line_decl = 1;
  236. print_line = 0;
  237. }
  238. print_line {
  239. if (/[^ \t\f\v\r\n]/ && needs_line_decl && !clean_mode) {
  240. print "#line " FNR;
  241. needs_line_decl = 0;
  242. }
  243. print;
  244. }
  245. END {
  246. if (!exit_okay) {
  247. # We're exiting due to an error. Don't do anything else.
  248. }
  249. else if (num_tests) {
  250. if (!main_post_done) {
  251. main_post();
  252. print "";
  253. print " return nf == 0 ? 0 : 1;";
  254. }
  255. print "}";
  256. }
  257. else {
  258. error("Expected at least one #test line.");
  259. }
  260. }
  261. ### Functions ###
  262. function test_pre()
  263. {
  264. if (in_main())
  265. in_main_error();
  266. if (in_test) {
  267. finish_test();
  268. print "";
  269. }
  270. ++num_tests;
  271. }
  272. function duplicate_check()
  273. {
  274. # Confirm that the test name is a valid C identifier.
  275. if (!match(cur_test, "^" pp_test_name "$")) {
  276. error_with_line("Malformed test name \"" cur_test \
  277. "\" (must be a C identifier).");
  278. }
  279. # Verify that it has not already been used.
  280. if (cur_test in test_registry) {
  281. error_with_line("Test \"" cur_test "\" already exists.");
  282. }
  283. # Verify that any implied test case is not a repeat.
  284. if (num_cur_tests == 0 && (cur_tcase, 0, 0) in tcase_test_map) {
  285. error_with_line("Test Case \"" name "\" already exists.");
  286. }
  287. }
  288. function test_post()
  289. {
  290. print "START_TEST(" cur_test ")";
  291. print "{";
  292. if (!clean_mode)
  293. print "#line " FNR+1;
  294. needs_line_decl = 0;
  295. }
  296. function main_post()
  297. {
  298. if (main_post_done)
  299. error_with_line("main-post specified multiple times.");
  300. if (!main_pre_done)
  301. main_pre();
  302. main_post_done = 1;
  303. print "";
  304. print_runner_bindings();
  305. print "";
  306. print " srunner_run_all(sr, CK_ENV);";
  307. print " nf = srunner_ntests_failed(sr);";
  308. print " srunner_free(sr);";
  309. }
  310. function in_main()
  311. {
  312. return main_pre_done || main_post_done;
  313. }
  314. function in_main_error()
  315. {
  316. error_with_line("Cannot specify tests after main-pre or main-post.");
  317. }
  318. function main_pre()
  319. {
  320. if (main_post_done)
  321. error_with_line("main-pre specified after main-post.");
  322. if (main_pre_done)
  323. error_with_line("main-pre specified multiple times.");
  324. main_pre_done = 1;
  325. finish_test();
  326. print "";
  327. print "int main(void)";
  328. print "{";
  329. print_main_declarations();
  330. }
  331. function suite_var_name(num)
  332. {
  333. return "s" num+1;
  334. }
  335. function tcase_var_name(snum, tcnum)
  336. {
  337. return "tc" snum+1 "_" tcnum+1;
  338. }
  339. function print_main_declarations()
  340. {
  341. for (i=0; i != num_suites; ++i) {
  342. s = suite_names[i];
  343. svar = suite_var_name(i);
  344. print " Suite *" svar " = suite_create(" string_encode(s) ");";
  345. for (j=0; j != suite_num_tcases[s]; ++j) {
  346. tc = suite_tcase_map[s, j];
  347. tcvar = tcase_var_name(i, j);
  348. print " TCase *" tcvar " = tcase_create(" \
  349. string_encode(tc) ");";
  350. }
  351. }
  352. print " SRunner *sr = srunner_create(s1);";
  353. print " int nf;";
  354. }
  355. function string_encode(raw)
  356. {
  357. # The next line might look funny, but remember that the first
  358. # argument will go through both string interpolation /and/ regex
  359. # interpolation, so the backslashes must be double-escaped. The
  360. # substitution string is supposed to result in an actual
  361. # double-backslash.
  362. gsub("\\\\", "\\\\", raw);
  363. gsub("\"", "\\\"", raw);
  364. return "\"" raw "\"";
  365. }
  366. function print_runner_bindings()
  367. {
  368. for (i=0; i != num_suites; ++i) {
  369. s = suite_names[i];
  370. svar = suite_var_name(i);
  371. for (j=0; j != suite_num_tcases[s]; ++j) {
  372. tc = suite_tcase_map[s, j];
  373. tcvar = tcase_var_name(i, j);
  374. print " suite_add_tcase(" svar ", " tcvar ");";
  375. for (k=0; k != tcase_num_tests[tc]; ++k) {
  376. t = tcase_test_map[tc, k, test_name];
  377. test_type = tcase_test_map[tc, k, test_type_flag];
  378. if (test_type == 0) {
  379. print " tcase_add_test(" tcvar ", " t ");";
  380. }
  381. else if (test_type == 1) {
  382. print " tcase_add_loop_test(" tcvar ", " t ", " \
  383. test_parameters[t, arg1] ", " test_parameters[t, arg2] \
  384. ");";
  385. }
  386. else if (test_type == 2) {
  387. print " tcase_add_exit_test(" tcvar ", " t ", " \
  388. test_parameters[t, arg1] ");";
  389. }
  390. else if (test_type == 3) {
  391. print " tcase_add_test_raise_signal(" tcvar ", " t ", " \
  392. test_parameters[t, arg1] ");";
  393. }
  394. else if (test_type == 4) {
  395. print " tcase_add_loop_exit_test(" tcvar ", " t ", " \
  396. test_parameters[t, arg1] ", " test_parameters[t, arg2] \
  397. ", " test_parameters[t, arg3] ");";
  398. }
  399. else if (test_type == 5) {
  400. print " tcase_add_loop_test_raise_signal(" tcvar ", " t \
  401. ", " test_parameters[t, arg1] ", " test_parameters[t, arg2] \
  402. ", " test_parameters[t, arg3] ");";
  403. }
  404. }
  405. }
  406. }
  407. if (num_suites > 1) {
  408. print "";
  409. for (i=1; i != num_suites; ++i) {
  410. svar = suite_var_name(i);
  411. print " srunner_add_suite(sr, " svar ");";
  412. }
  413. }
  414. }
  415. function register_test()
  416. {
  417. if (num_cur_tcases == 0) {
  418. suite_names[num_suites++] = cur_suite;
  419. }
  420. if (num_cur_tests == 0) {
  421. suite_tcase_map[cur_suite, num_cur_tcases++] = cur_tcase;
  422. suite_num_tcases[cur_suite] = num_cur_tcases;
  423. }
  424. tcase_test_map[cur_tcase, num_cur_tests, test_name] = cur_test;
  425. tcase_test_map[cur_tcase, num_cur_tests++, test_type_flag] = test_type;
  426. tcase_num_tests[cur_tcase] = num_cur_tests;
  427. test_registry[cur_test] = 1;
  428. # Store arguments to array
  429. test_parameters[cur_test, arg1] = arr[2];
  430. test_parameters[cur_test, arg2] = arr[3];
  431. test_parameters[cur_test, arg3] = arr[4];
  432. }
  433. function finish_test()
  434. {
  435. if (in_test) {
  436. in_test = 0;
  437. print "}";
  438. print "END_TEST";
  439. }
  440. }
  441. function print_boilerplate()
  442. {
  443. print "/*";
  444. print " * DO NOT EDIT THIS FILE. Generated by " progname ".";
  445. if (!FILENAME || FILENAME == "-") {
  446. clean_mode=1;
  447. is_stdin=1;
  448. }
  449. if (is_stdin)
  450. srcfile = "(standard input)";
  451. else
  452. srcfile = "\"" FILENAME "\"";
  453. print " * Edit the original source file " srcfile " instead.";
  454. print " */";
  455. print "";
  456. print "#include <check.h>";
  457. print "";
  458. if (!clean_mode)
  459. print "#line 1 " string_encode(FILENAME)
  460. }
  461. function error_with_line(err)
  462. {
  463. error((is_stdin ? "(standard input)" : FILENAME) " line " FNR ": " err);
  464. }
  465. function error(err)
  466. {
  467. print progname ": " err > "/dev/stderr";
  468. exit_okay = 0;
  469. exit 1;
  470. }