runner.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "runner.h"
  25. #include "task.h"
  26. #include "uv.h"
  27. char executable_path[sizeof(executable_path)];
  28. static int compare_task(const void* va, const void* vb) {
  29. const task_entry_t* a = va;
  30. const task_entry_t* b = vb;
  31. return strcmp(a->task_name, b->task_name);
  32. }
  33. const char* fmt(double d) {
  34. static char buf[1024];
  35. static char* p;
  36. uint64_t v;
  37. if (p == NULL)
  38. p = buf;
  39. p += 31;
  40. if (p >= buf + sizeof(buf))
  41. return "<buffer too small>";
  42. v = (uint64_t) d;
  43. #if 0 /* works but we don't care about fractional precision */
  44. if (d - v >= 0.01) {
  45. *--p = '0' + (uint64_t) (d * 100) % 10;
  46. *--p = '0' + (uint64_t) (d * 10) % 10;
  47. *--p = '.';
  48. }
  49. #endif
  50. if (v == 0)
  51. *--p = '0';
  52. while (v) {
  53. if (v) *--p = '0' + (v % 10), v /= 10;
  54. if (v) *--p = '0' + (v % 10), v /= 10;
  55. if (v) *--p = '0' + (v % 10), v /= 10;
  56. if (v) *--p = ',';
  57. }
  58. return p;
  59. }
  60. int run_tests(int benchmark_output) {
  61. int actual;
  62. int total;
  63. int passed;
  64. int failed;
  65. int skipped;
  66. int current;
  67. int test_result;
  68. int skip;
  69. task_entry_t* task;
  70. /* Count the number of tests. */
  71. actual = 0;
  72. total = 0;
  73. for (task = TASKS; task->main; task++, actual++) {
  74. if (!task->is_helper) {
  75. total++;
  76. }
  77. }
  78. /* Keep platform_output first. */
  79. skip = (actual > 0 && 0 == strcmp(TASKS[0].task_name, "platform_output"));
  80. qsort(TASKS + skip, actual - skip, sizeof(TASKS[0]), compare_task);
  81. fprintf(stderr, "1..%d\n", total);
  82. fflush(stderr);
  83. /* Run all tests. */
  84. passed = 0;
  85. failed = 0;
  86. skipped = 0;
  87. current = 1;
  88. for (task = TASKS; task->main; task++) {
  89. if (task->is_helper) {
  90. continue;
  91. }
  92. test_result = run_test(task->task_name, benchmark_output, current);
  93. switch (test_result) {
  94. case TEST_OK: passed++; break;
  95. case TEST_SKIP: skipped++; break;
  96. default: failed++;
  97. }
  98. current++;
  99. }
  100. return failed;
  101. }
  102. void log_tap_result(int test_count,
  103. const char* test,
  104. int status,
  105. process_info_t* process) {
  106. const char* result;
  107. const char* directive;
  108. char reason[1024];
  109. int reason_length;
  110. switch (status) {
  111. case TEST_OK:
  112. result = "ok";
  113. directive = "";
  114. break;
  115. case TEST_SKIP:
  116. result = "ok";
  117. directive = " # SKIP ";
  118. break;
  119. default:
  120. result = "not ok";
  121. directive = "";
  122. }
  123. if (status == TEST_SKIP && process_output_size(process) > 0) {
  124. process_read_last_line(process, reason, sizeof reason);
  125. reason_length = strlen(reason);
  126. if (reason_length > 0 && reason[reason_length - 1] == '\n')
  127. reason[reason_length - 1] = '\0';
  128. } else {
  129. reason[0] = '\0';
  130. }
  131. fprintf(stderr, "%s %d - %s%s%s\n", result, test_count, test, directive, reason);
  132. fflush(stderr);
  133. }
  134. int run_test(const char* test,
  135. int benchmark_output,
  136. int test_count) {
  137. char errmsg[1024] = "";
  138. process_info_t processes[1024];
  139. process_info_t *main_proc;
  140. task_entry_t* task;
  141. int timeout_multiplier;
  142. int process_count;
  143. int result;
  144. int status;
  145. int i;
  146. status = 255;
  147. main_proc = NULL;
  148. process_count = 0;
  149. #ifndef _WIN32
  150. /* Clean up stale socket from previous run. */
  151. remove(TEST_PIPENAME);
  152. remove(TEST_PIPENAME_2);
  153. remove(TEST_PIPENAME_3);
  154. #endif
  155. /* If it's a helper the user asks for, start it directly. */
  156. for (task = TASKS; task->main; task++) {
  157. if (task->is_helper && strcmp(test, task->process_name) == 0) {
  158. return task->main();
  159. }
  160. }
  161. /* Start the helpers first. */
  162. for (task = TASKS; task->main; task++) {
  163. if (strcmp(test, task->task_name) != 0) {
  164. continue;
  165. }
  166. /* Skip the test itself. */
  167. if (!task->is_helper) {
  168. continue;
  169. }
  170. if (process_start(task->task_name,
  171. task->process_name,
  172. &processes[process_count],
  173. 1 /* is_helper */) == -1) {
  174. snprintf(errmsg,
  175. sizeof errmsg,
  176. "Process `%s` failed to start.",
  177. task->process_name);
  178. goto out;
  179. }
  180. process_count++;
  181. }
  182. /* Now start the test itself. */
  183. for (task = TASKS; task->main; task++) {
  184. if (strcmp(test, task->task_name) != 0) {
  185. continue;
  186. }
  187. if (task->is_helper) {
  188. continue;
  189. }
  190. if (process_start(task->task_name,
  191. task->process_name,
  192. &processes[process_count],
  193. 0 /* !is_helper */) == -1) {
  194. snprintf(errmsg,
  195. sizeof errmsg,
  196. "Process `%s` failed to start.",
  197. task->process_name);
  198. goto out;
  199. }
  200. main_proc = &processes[process_count];
  201. process_count++;
  202. break;
  203. }
  204. if (main_proc == NULL) {
  205. snprintf(errmsg,
  206. sizeof errmsg,
  207. "No test with that name: %s",
  208. test);
  209. goto out;
  210. }
  211. timeout_multiplier = 1;
  212. #ifndef _WIN32
  213. do {
  214. const char* var;
  215. var = getenv("UV_TEST_TIMEOUT_MULTIPLIER");
  216. if (var == NULL)
  217. break;
  218. timeout_multiplier = atoi(var);
  219. if (timeout_multiplier <= 0)
  220. timeout_multiplier = 1;
  221. } while (0);
  222. #endif
  223. result = process_wait(main_proc, 1, task->timeout * timeout_multiplier);
  224. if (result == -1) {
  225. FATAL("process_wait failed");
  226. } else if (result == -2) {
  227. /* Don't have to clean up the process, process_wait() has killed it. */
  228. snprintf(errmsg,
  229. sizeof errmsg,
  230. "timeout");
  231. goto out;
  232. }
  233. status = process_reap(main_proc);
  234. if (status != TEST_OK) {
  235. snprintf(errmsg,
  236. sizeof errmsg,
  237. "exit code %d",
  238. status);
  239. goto out;
  240. }
  241. if (benchmark_output) {
  242. /* Give the helpers time to clean up their act. */
  243. uv_sleep(1000);
  244. }
  245. out:
  246. /* Reap running processes except the main process, it's already dead. */
  247. for (i = 0; i < process_count - 1; i++) {
  248. process_terminate(&processes[i]);
  249. }
  250. if (process_count > 0 &&
  251. process_wait(processes, process_count - 1, -1) < 0) {
  252. FATAL("process_wait failed");
  253. }
  254. log_tap_result(test_count, test, status, &processes[i]);
  255. /* Show error and output from processes if the test failed. */
  256. if ((status != TEST_OK && status != TEST_SKIP) || task->show_output) {
  257. if (strlen(errmsg) > 0)
  258. fprintf(stderr, "# %s\n", errmsg);
  259. fprintf(stderr, "# ");
  260. fflush(stderr);
  261. for (i = 0; i < process_count; i++) {
  262. switch (process_output_size(&processes[i])) {
  263. case -1:
  264. fprintf(stderr, "Output from process `%s`: (unavailable)\n",
  265. process_get_name(&processes[i]));
  266. fflush(stderr);
  267. break;
  268. case 0:
  269. fprintf(stderr, "Output from process `%s`: (no output)\n",
  270. process_get_name(&processes[i]));
  271. fflush(stderr);
  272. break;
  273. default:
  274. fprintf(stderr, "Output from process `%s`:\n", process_get_name(&processes[i]));
  275. fflush(stderr);
  276. process_copy_output(&processes[i], stderr);
  277. break;
  278. }
  279. }
  280. /* In benchmark mode show concise output from the main process. */
  281. } else if (benchmark_output) {
  282. switch (process_output_size(main_proc)) {
  283. case -1:
  284. fprintf(stderr, "%s: (unavailable)\n", test);
  285. fflush(stderr);
  286. break;
  287. case 0:
  288. fprintf(stderr, "%s: (no output)\n", test);
  289. fflush(stderr);
  290. break;
  291. default:
  292. for (i = 0; i < process_count; i++) {
  293. process_copy_output(&processes[i], stderr);
  294. }
  295. break;
  296. }
  297. }
  298. /* Clean up all process handles. */
  299. for (i = 0; i < process_count; i++) {
  300. process_cleanup(&processes[i]);
  301. }
  302. return status;
  303. }
  304. /* Returns the status code of the task part
  305. * or 255 if no matching task was not found.
  306. */
  307. int run_test_part(const char* test, const char* part) {
  308. task_entry_t* task;
  309. int r;
  310. for (task = TASKS; task->main; task++) {
  311. if (strcmp(test, task->task_name) == 0 &&
  312. strcmp(part, task->process_name) == 0) {
  313. r = task->main();
  314. return r;
  315. }
  316. }
  317. fprintf(stderr, "No test part with that name: %s:%s\n", test, part);
  318. fflush(stderr);
  319. return 255;
  320. }
  321. static int find_helpers(const task_entry_t* task,
  322. const task_entry_t** helpers) {
  323. const task_entry_t* helper;
  324. int n_helpers;
  325. for (n_helpers = 0, helper = TASKS; helper->main; helper++) {
  326. if (helper->is_helper && strcmp(helper->task_name, task->task_name) == 0) {
  327. *helpers++ = helper;
  328. n_helpers++;
  329. }
  330. }
  331. return n_helpers;
  332. }
  333. void print_tests(FILE* stream) {
  334. const task_entry_t* helpers[1024];
  335. const task_entry_t* task;
  336. int n_helpers;
  337. int n_tasks;
  338. int i;
  339. for (n_tasks = 0, task = TASKS; task->main; n_tasks++, task++);
  340. qsort(TASKS, n_tasks, sizeof(TASKS[0]), compare_task);
  341. for (task = TASKS; task->main; task++) {
  342. if (task->is_helper) {
  343. continue;
  344. }
  345. n_helpers = find_helpers(task, helpers);
  346. if (n_helpers) {
  347. printf("%-25s (helpers:", task->task_name);
  348. for (i = 0; i < n_helpers; i++) {
  349. printf(" %s", helpers[i]->process_name);
  350. }
  351. printf(")\n");
  352. } else {
  353. printf("%s\n", task->task_name);
  354. }
  355. }
  356. }
  357. void print_lines(const char* buffer, size_t size, FILE* stream) {
  358. const char* start;
  359. const char* end;
  360. start = buffer;
  361. while ((end = memchr(start, '\n', &buffer[size] - start))) {
  362. fputs("# ", stream);
  363. fwrite(start, 1, (int)(end - start), stream);
  364. fputs("\n", stream);
  365. fflush(stream);
  366. start = end + 1;
  367. }
  368. end = &buffer[size];
  369. if (start < end) {
  370. fputs("# ", stream);
  371. fwrite(start, 1, (int)(end - start), stream);
  372. fputs("\n", stream);
  373. fflush(stream);
  374. }
  375. }