tests.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /*
  2. Stupidly simple test framework
  3. Copyright (C) 2001-2009, Joe Orton <[email protected]>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "config.h"
  17. #include <sys/types.h>
  18. #include <stdio.h>
  19. #ifdef HAVE_SIGNAL_H
  20. #include <signal.h>
  21. #endif
  22. #ifdef HAVE_UNISTD_H
  23. #include <unistd.h>
  24. #endif
  25. #ifdef HAVE_STRING_H
  26. #include <string.h>
  27. #endif
  28. #ifdef HAVE_STDLIB_H
  29. #include <stdlib.h>
  30. #endif
  31. #ifdef HAVE_ERRNO_H
  32. #include <errno.h>
  33. #endif
  34. #ifdef HAVE_LOCALE_H
  35. #include <locale.h>
  36. #endif
  37. #include "ne_string.h"
  38. #include "ne_utils.h"
  39. #include "ne_socket.h"
  40. #include "ne_i18n.h"
  41. #include "tests.h"
  42. #include "child.h"
  43. char test_context[BUFSIZ];
  44. int have_context = 0;
  45. static FILE *child_debug, *debug;
  46. char **test_argv;
  47. int test_argc;
  48. const char *test_suite;
  49. int test_num;
  50. static int quiet, count;
  51. /* statistics for all tests so far */
  52. static int passes = 0, fails = 0, skipped = 0, warnings = 0;
  53. /* per-test globals: */
  54. static int warned, aborted = 0;
  55. static const char *test_name; /* current test name */
  56. static int use_colour = 0;
  57. static int flag_child;
  58. /* resource for ANSI escape codes:
  59. * http://www.isthe.com/chongo/tech/comp/ansi_escapes.html */
  60. #define COL(x) do { if (use_colour) printf("\033[" x "m"); } while (0)
  61. #define NOCOL COL("00")
  62. void t_context(const char *context, ...)
  63. {
  64. va_list ap;
  65. va_start(ap, context);
  66. ne_vsnprintf(test_context, BUFSIZ, context, ap);
  67. va_end(ap);
  68. if (flag_child) {
  69. NE_DEBUG(NE_DBG_HTTP, "context: %s\n", test_context);
  70. }
  71. have_context = 1;
  72. }
  73. void t_warning(const char *str, ...)
  74. {
  75. va_list ap;
  76. COL("43;01"); printf("WARNING:"); NOCOL;
  77. putchar(' ');
  78. va_start(ap, str);
  79. vprintf(str, ap);
  80. va_end(ap);
  81. warnings++;
  82. warned++;
  83. putchar('\n');
  84. }
  85. #define TEST_DEBUG \
  86. (NE_DBG_HTTP | NE_DBG_SOCKET | NE_DBG_HTTPBODY | NE_DBG_HTTPAUTH | \
  87. NE_DBG_LOCKS | NE_DBG_XMLPARSE | NE_DBG_XML | NE_DBG_SSL | \
  88. NE_DBG_HTTPPLAIN)
  89. #define W(m) do { if (write(STDOUT_FILENO, m, strlen(m)) < 0) _exit(99); } while(0)
  90. #define W_RED(m) do { if (use_colour) W("\033[41;37;01m"); \
  91. W(m); if (use_colour) W("\033[00m\n"); } while (0);
  92. #ifndef NEON_NO_TEST_CHILD
  93. /* Signal handler for child processes. */
  94. static void child_segv(int signo)
  95. {
  96. signal(SIGSEGV, SIG_DFL);
  97. signal(SIGABRT, SIG_DFL);
  98. W_RED("Fatal signal in child!");
  99. kill(getpid(), SIGSEGV);
  100. minisleep();
  101. }
  102. /* Signal handler for parent process. */
  103. static void parent_segv(int signo)
  104. {
  105. signal(SIGSEGV, SIG_DFL);
  106. signal(SIGABRT, SIG_DFL);
  107. if (signo == SIGSEGV) {
  108. W_RED("FAILED - Segmentation fault--\n");
  109. }
  110. else if (signo == SIGABRT) {
  111. W_RED("ABORTED\n");
  112. }
  113. else {
  114. W_RED("-- Unexpected signal! --\n");
  115. }
  116. reap_server();
  117. kill(getpid(), signo);
  118. minisleep();
  119. }
  120. void in_child(void)
  121. {
  122. ne_debug_init(child_debug, TEST_DEBUG);
  123. NE_DEBUG(TEST_DEBUG, "**** Child forked for test %s ****\n", test_name);
  124. signal(SIGSEGV, child_segv);
  125. signal(SIGABRT, child_segv);
  126. flag_child = 1;
  127. }
  128. #endif
  129. static const char dots[] = "......................";
  130. static void print_prefix(int n)
  131. {
  132. if (quiet) {
  133. printf("\r%s%.*s %2u/%2u ", test_suite,
  134. (int) (strlen(dots) - strlen(test_suite)), dots,
  135. n + 1, count);
  136. }
  137. else {
  138. if (warned) {
  139. printf(" %s ", dots);
  140. }
  141. else {
  142. printf("\r%2d. %s%.*s ", n, test_name,
  143. (int) (strlen(dots) - strlen(test_name)), dots);
  144. }
  145. }
  146. fflush(stdout);
  147. }
  148. int main(int argc, char *argv[])
  149. {
  150. int n;
  151. char *tmp;
  152. /* get basename(argv[0]) */
  153. test_suite = strrchr(argv[0], '/');
  154. if (test_suite == NULL) {
  155. test_suite = argv[0];
  156. } else {
  157. test_suite++;
  158. }
  159. if (strncmp(test_suite, "lt-", 3) == 0)
  160. test_suite += 3;
  161. #ifdef HAVE_SETLOCALE
  162. setlocale(LC_MESSAGES, "");
  163. #endif
  164. ne_i18n_init(NULL);
  165. #if defined(HAVE_ISATTY) && defined(STDOUT_FILENO)
  166. if (isatty(STDOUT_FILENO)) {
  167. use_colour = 1;
  168. }
  169. #endif
  170. test_argc = argc;
  171. test_argv = argv;
  172. debug = fopen("debug.log", "a");
  173. if (debug == NULL) {
  174. fprintf(stderr, "%s: Could not open debug.log: %s\n", test_suite,
  175. strerror(errno));
  176. return -1;
  177. }
  178. child_debug = fopen("child.log", "a");
  179. if (child_debug == NULL) {
  180. fprintf(stderr, "%s: Could not open child.log: %s\n", test_suite,
  181. strerror(errno));
  182. fclose(debug);
  183. return -1;
  184. }
  185. if (tests[0].fn == NULL) {
  186. printf("-> no tests found in `%s'\n", test_suite);
  187. return -1;
  188. }
  189. #ifndef NEON_NO_TEST_CHILD
  190. /* install special SEGV handler. */
  191. signal(SIGSEGV, parent_segv);
  192. signal(SIGABRT, parent_segv);
  193. #endif
  194. /* test the "no-debugging" mode of ne_debug. */
  195. ne_debug_init(NULL, 0);
  196. NE_DEBUG(TEST_DEBUG, "This message should go to /dev/null");
  197. /* enable debugging for real. */
  198. ne_debug_init(debug, TEST_DEBUG);
  199. NE_DEBUG(TEST_DEBUG | NE_DBG_FLUSH, "Version string: %s\n",
  200. ne_version_string());
  201. /* another silly test. */
  202. NE_DEBUG(0, "This message should also go to /dev/null");
  203. if (ne_sock_init()) {
  204. COL("43;01"); printf("WARNING:"); NOCOL;
  205. printf(" Socket library initialization failed.\n");
  206. }
  207. if ((tmp = getenv("TEST_QUIET")) != NULL && strcmp(tmp, "1") == 0) {
  208. quiet = 1;
  209. }
  210. if (!quiet)
  211. printf("-> running `%s':\n", test_suite);
  212. for (count = 0; tests[count].fn; count++)
  213. /* nullop */;
  214. for (n = 0; !aborted && tests[n].fn != NULL; n++) {
  215. int result, is_xfail = 0;
  216. #ifdef NEON_MEMLEAK
  217. size_t allocated = ne_alloc_used;
  218. int is_xleaky = 0;
  219. #endif
  220. test_name = tests[n].name;
  221. print_prefix(n);
  222. have_context = 0;
  223. test_num = n;
  224. warned = 0;
  225. fflush(stdout);
  226. NE_DEBUG(TEST_DEBUG, "******* Running test %d: %s ********\n",
  227. n, test_name);
  228. /* run the test. */
  229. result = tests[n].fn();
  230. #ifdef NEON_MEMLEAK
  231. /* issue warnings for memory leaks, if requested */
  232. if ((tests[n].flags & T_CHECK_LEAKS) && result == OK &&
  233. ne_alloc_used > allocated) {
  234. t_context("memory leak of %" NE_FMT_SIZE_T " bytes",
  235. ne_alloc_used - allocated);
  236. fprintf(debug, "Blocks leaked: ");
  237. ne_alloc_dump(debug);
  238. result = FAIL;
  239. } else if (tests[n].flags & T_EXPECT_LEAKS && result == OK &&
  240. ne_alloc_used == allocated) {
  241. t_context("expected memory leak not detected");
  242. result = FAIL;
  243. } else if (tests[n].flags & T_EXPECT_LEAKS && result == OK) {
  244. fprintf(debug, "Blocks leaked (expected): ");
  245. ne_alloc_dump(debug);
  246. is_xleaky = 1;
  247. }
  248. #endif
  249. if (tests[n].flags & T_EXPECT_FAIL) {
  250. if (result == OK) {
  251. t_context("test passed but expected failure");
  252. result = FAIL;
  253. } else if (result == FAIL) {
  254. result = OK;
  255. is_xfail = 1;
  256. }
  257. }
  258. print_prefix(n);
  259. switch (result) {
  260. case OK:
  261. passes++;
  262. if (is_xfail) {
  263. COL("32;07");
  264. printf("XFAIL");
  265. } else if (!quiet) {
  266. COL("32");
  267. printf("pass");
  268. }
  269. NOCOL;
  270. if (quiet && is_xfail) {
  271. printf(" - %s", test_name);
  272. if (have_context) {
  273. printf(" (%s)", test_context);
  274. }
  275. }
  276. if (warned && !quiet) {
  277. printf(" (with %d warning%s)", warned, (warned > 1)?"s":"");
  278. }
  279. #ifdef NEON_MEMLEAK
  280. if (is_xleaky) {
  281. if (quiet) {
  282. printf("expected leak - %s: %" NE_FMT_SIZE_T " bytes",
  283. test_name, ne_alloc_used - allocated);
  284. }
  285. else {
  286. printf(" (expected leak, %" NE_FMT_SIZE_T " bytes)",
  287. ne_alloc_used - allocated);
  288. }
  289. }
  290. #endif
  291. if (!quiet || is_xfail) putchar('\n');
  292. break;
  293. case FAILHARD:
  294. aborted = 1;
  295. COL("41;37;01"); printf("fatal error - "); NOCOL;
  296. /* fall-through */
  297. case FAIL:
  298. COL("41;37;01"); printf("FAIL"); NOCOL;
  299. if (quiet) {
  300. printf(" - %s", test_name);
  301. }
  302. if (have_context) {
  303. printf(" (%s)", test_context);
  304. }
  305. putchar('\n');
  306. fails++;
  307. break;
  308. case SKIPREST:
  309. aborted = 1;
  310. /* fall-through */
  311. case SKIP:
  312. COL("44;37;01"); printf("SKIPPED"); NOCOL;
  313. if (quiet) {
  314. printf(" - %s", test_name);
  315. }
  316. if (have_context) {
  317. printf(" (%s)", test_context);
  318. }
  319. putchar('\n');
  320. skipped++;
  321. break;
  322. default:
  323. COL("41;37;01"); printf("OOPS"); NOCOL;
  324. printf(" unexpected test result `%d'\n", result);
  325. break;
  326. }
  327. #ifndef NEON_NO_TEST_CHILD
  328. reap_server();
  329. #endif
  330. if (quiet) {
  331. print_prefix(n);
  332. }
  333. }
  334. /* discount skipped tests */
  335. if (skipped) {
  336. if (!quiet)
  337. printf("-> %d %s.\n", skipped,
  338. skipped == 1 ? "test was skipped" : "tests were skipped");
  339. n -= skipped;
  340. }
  341. /* print the summary. */
  342. if (skipped && n == 0) {
  343. if (quiet)
  344. puts("(all skipped)");
  345. else
  346. printf("<- all tests skipped for `%s'.\n", test_suite);
  347. } else {
  348. if (quiet) {
  349. printf("\r%s%.*s %2u/%2u ", test_suite,
  350. (int) (strlen(dots) - strlen(test_suite)), dots,
  351. passes, count);
  352. if (fails == 0) {
  353. COL("32");
  354. printf("passed");
  355. NOCOL;
  356. putchar(' ');
  357. }
  358. else {
  359. printf("passed, %d failed ", fails);
  360. }
  361. if (skipped)
  362. printf("(%d skipped) ", skipped);
  363. }
  364. else /* !quiet */
  365. printf("<- summary for `%s': "
  366. "of %d tests run: %d passed, %d failed. %.1f%%\n",
  367. test_suite, n, passes, fails, 100*(float)passes/n);
  368. if (warnings) {
  369. if (quiet) {
  370. printf("(%d warning%s)\n", warnings,
  371. warnings > 1 ? "s" : "");
  372. }
  373. else {
  374. printf("-> %d warning%s issued.\n", warnings,
  375. warnings==1?" was":"s were");
  376. }
  377. }
  378. else if (quiet) {
  379. putchar('\n');
  380. }
  381. }
  382. if (fclose(debug)) {
  383. fprintf(stderr, "Error closing debug.log: %s\n", strerror(errno));
  384. fails = 1;
  385. }
  386. if (fclose(child_debug)) {
  387. fprintf(stderr, "Error closing child.log: %s\n", strerror(errno));
  388. fails = 1;
  389. }
  390. ne_sock_exit();
  391. return fails;
  392. }