minicheck.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* Miniature re-implementation of the "check" library.
  2. *
  3. * This is intended to support just enough of check to run the Expat
  4. * tests. This interface is based entirely on the portion of the
  5. * check library being used.
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <setjmp.h>
  10. #include <assert.h>
  11. #include "minicheck.h"
  12. Suite *
  13. suite_create(char *name)
  14. {
  15. Suite *suite = (Suite *) calloc(1, sizeof(Suite));
  16. if (suite != NULL) {
  17. suite->name = name;
  18. }
  19. return suite;
  20. }
  21. TCase *
  22. tcase_create(char *name)
  23. {
  24. TCase *tc = (TCase *) calloc(1, sizeof(TCase));
  25. if (tc != NULL) {
  26. tc->name = name;
  27. }
  28. return tc;
  29. }
  30. void
  31. suite_add_tcase(Suite *suite, TCase *tc)
  32. {
  33. assert(suite != NULL);
  34. assert(tc != NULL);
  35. assert(tc->next_tcase == NULL);
  36. tc->next_tcase = suite->tests;
  37. suite->tests = tc;
  38. }
  39. void
  40. tcase_add_checked_fixture(TCase *tc,
  41. tcase_setup_function setup,
  42. tcase_teardown_function teardown)
  43. {
  44. assert(tc != NULL);
  45. tc->setup = setup;
  46. tc->teardown = teardown;
  47. }
  48. void
  49. tcase_add_test(TCase *tc, tcase_test_function test)
  50. {
  51. assert(tc != NULL);
  52. if (tc->allocated == tc->ntests) {
  53. int nalloc = tc->allocated + 100;
  54. size_t new_size = sizeof(tcase_test_function) * nalloc;
  55. tcase_test_function *new_tests = realloc(tc->tests, new_size);
  56. assert(new_tests != NULL);
  57. if (new_tests != tc->tests) {
  58. free(tc->tests);
  59. tc->tests = new_tests;
  60. }
  61. tc->allocated = nalloc;
  62. }
  63. tc->tests[tc->ntests] = test;
  64. tc->ntests++;
  65. }
  66. SRunner *
  67. srunner_create(Suite *suite)
  68. {
  69. SRunner *runner = calloc(1, sizeof(SRunner));
  70. if (runner != NULL) {
  71. runner->suite = suite;
  72. }
  73. return runner;
  74. }
  75. static jmp_buf env;
  76. static char const *_check_current_function = NULL;
  77. static int _check_current_lineno = -1;
  78. static char const *_check_current_filename = NULL;
  79. void
  80. _check_set_test_info(char const *function, char const *filename, int lineno)
  81. {
  82. _check_current_function = function;
  83. _check_current_lineno = lineno;
  84. _check_current_filename = filename;
  85. }
  86. static void
  87. add_failure(SRunner *runner, int verbosity)
  88. {
  89. runner->nfailures++;
  90. if (verbosity >= CK_VERBOSE) {
  91. printf("%s:%d: %s\n", _check_current_filename,
  92. _check_current_lineno, _check_current_function);
  93. }
  94. }
  95. void
  96. srunner_run_all(SRunner *runner, int verbosity)
  97. {
  98. Suite *suite;
  99. TCase *tc;
  100. assert(runner != NULL);
  101. suite = runner->suite;
  102. tc = suite->tests;
  103. while (tc != NULL) {
  104. int i;
  105. for (i = 0; i < tc->ntests; ++i) {
  106. runner->nchecks++;
  107. if (tc->setup != NULL) {
  108. /* setup */
  109. if (setjmp(env)) {
  110. add_failure(runner, verbosity);
  111. continue;
  112. }
  113. tc->setup();
  114. }
  115. /* test */
  116. if (setjmp(env)) {
  117. add_failure(runner, verbosity);
  118. continue;
  119. }
  120. (tc->tests[i])();
  121. /* teardown */
  122. if (tc->teardown != NULL) {
  123. if (setjmp(env)) {
  124. add_failure(runner, verbosity);
  125. continue;
  126. }
  127. tc->teardown();
  128. }
  129. }
  130. tc = tc->next_tcase;
  131. }
  132. if (verbosity) {
  133. int passed = runner->nchecks - runner->nfailures;
  134. double percentage = ((double) passed) / runner->nchecks;
  135. int display = (int) (percentage * 100);
  136. printf("%d%%: Checks: %d, Failed: %d\n",
  137. display, runner->nchecks, runner->nfailures);
  138. }
  139. }
  140. void
  141. _fail_unless(int condition, const char *file, int line, char *msg)
  142. {
  143. /* Always print the error message so it isn't lost. In this case,
  144. we have a failure, so there's no reason to be quiet about what
  145. it is.
  146. */
  147. if (msg != NULL)
  148. printf("%s", msg);
  149. longjmp(env, 1);
  150. }
  151. int
  152. srunner_ntests_failed(SRunner *runner)
  153. {
  154. assert(runner != NULL);
  155. return runner->nfailures;
  156. }
  157. void
  158. srunner_free(SRunner *runner)
  159. {
  160. free(runner->suite);
  161. free(runner);
  162. }