tests_pass.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include <tools/ccanlint/ccanlint.h>
  2. #include <tools/tools.h>
  3. #include <ccan/take/take.h>
  4. #include <ccan/str/str.h>
  5. #include <ccan/foreach/foreach.h>
  6. #include <ccan/tal/path/path.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <unistd.h>
  11. #include <limits.h>
  12. #include <errno.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <err.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18. #include "tests_pass.h"
  19. bool do_valgrind = false;
  20. const char *valgrind_suppress = "";
  21. static const char *can_run(struct manifest *m)
  22. {
  23. unsigned int timeleft = default_timeout_ms;
  24. char *output;
  25. if (safe_mode)
  26. return "Safe mode enabled";
  27. if (!is_excluded("tests_pass_valgrind")
  28. && run_command(m, &timeleft, &output,
  29. "valgrind -q true")) {
  30. const char *sfile;
  31. do_valgrind = true;
  32. /* Check for suppressions file for all of CCAN. */
  33. sfile = path_join(m, ccan_dir, ".valgrind_suppressions");
  34. if (path_is_file(sfile))
  35. valgrind_suppress = tal_fmt(m, "--suppressions=%s",
  36. sfile);
  37. }
  38. return NULL;
  39. }
  40. static const char *concat(struct score *score, char *bits[])
  41. {
  42. unsigned int i;
  43. char *ret = tal_strdup(score, "");
  44. for (i = 0; bits[i]; i++) {
  45. if (i)
  46. ret = tal_strcat(score, take(ret), " ");
  47. ret = tal_strcat(score, take(ret), bits[i]);
  48. }
  49. return ret;
  50. }
  51. static void run_test(void *ctx,
  52. struct manifest *m,
  53. unsigned int *timeleft,
  54. struct ccan_file *i)
  55. {
  56. if (do_valgrind) {
  57. const char *options;
  58. options = concat(ctx,
  59. per_file_options(&tests_pass_valgrind, i));
  60. if (!streq(options, "FAIL")) {
  61. /* FIXME: Valgrind's output sucks. XML is
  62. * unreadable by humans *and* doesn't support
  63. * children reporting. */
  64. i->valgrind_log = tal_fmt(m,
  65. "%s.valgrind-log",
  66. i->compiled[COMPILE_NORMAL]);
  67. run_command_async(i, *timeleft,
  68. "valgrind -q"
  69. " --leak-check=full"
  70. " --log-fd=3 %s %s %s"
  71. " 3> %s",
  72. valgrind_suppress, options,
  73. i->compiled[COMPILE_NORMAL],
  74. i->valgrind_log);
  75. return;
  76. }
  77. }
  78. run_command_async(i, *timeleft, "%s",
  79. i->compiled[COMPILE_NORMAL]);
  80. }
  81. static void do_run_tests(struct manifest *m,
  82. unsigned int *timeleft,
  83. struct score *score)
  84. {
  85. struct list_head *list;
  86. struct ccan_file *i;
  87. char *cmdout;
  88. bool ok;
  89. score->total = 0;
  90. foreach_ptr(list, &m->run_tests, &m->api_tests) {
  91. list_for_each(list, i, list) {
  92. score->total++;
  93. if (verbose >= 2)
  94. printf(" %s...\n", i->name);
  95. run_test(score, m, timeleft, i);
  96. }
  97. }
  98. while ((i = collect_command(&ok, &cmdout)) != NULL) {
  99. if (!ok)
  100. score_file_error(score, i, 0, "%s", cmdout);
  101. else
  102. score->score++;
  103. if (verbose >= 2)
  104. printf(" ...%s\n", i->name);
  105. }
  106. if (score->score == score->total)
  107. score->pass = true;
  108. }
  109. /* Gcc's warn_unused_result is fascist bullshit. */
  110. #define doesnt_matter()
  111. static void run_under_debugger(struct manifest *m, struct score *score)
  112. {
  113. char *command;
  114. struct file_error *first;
  115. first = list_top(&score->per_file_errors, struct file_error, list);
  116. if (!ask("Should I run the first failing test under the debugger?"))
  117. return;
  118. command = tal_fmt(m, "gdb -ex 'break tap.c:139' -ex 'run' %s",
  119. first->file->compiled[COMPILE_NORMAL]);
  120. if (system(command)) {
  121. doesnt_matter();
  122. }
  123. }
  124. struct ccanlint tests_pass = {
  125. .key = "tests_pass",
  126. .name = "Module's run and api tests pass",
  127. .check = do_run_tests,
  128. .handle = run_under_debugger,
  129. .can_run = can_run,
  130. .needs = "tests_compile"
  131. };
  132. REGISTER_TEST(tests_pass);