int run_test(const char* test, int timeout, int benchmark_output, int test_count) { char errmsg[1024] = "no error"; process_info_t processes[1024]; process_info_t *main_proc; task_entry_t* task; int process_count; int result; int status; int i; status = 255; main_proc = NULL; process_count = 0; #ifndef _WIN32 /* Clean up stale socket from previous run. */ remove(TEST_PIPENAME); #endif /* If it's a helper the user asks for, start it directly. */ for (task = TASKS; task->main; task++) { if (task->is_helper && strcmp(test, task->process_name) == 0) { return task->main(); } } /* Start the helpers first. */ for (task = TASKS; task->main; task++) { if (strcmp(test, task->task_name) != 0) { continue; } /* Skip the test itself. */ if (!task->is_helper) { continue; } if (process_start(task->task_name, task->process_name, &processes[process_count], 1 /* is_helper */) == -1) { snprintf(errmsg, sizeof errmsg, "Process `%s` failed to start.", task->process_name); goto out; } process_count++; } /* Give the helpers time to settle. Race-y, fix this. */ uv_sleep(250); /* Now start the test itself. */ for (task = TASKS; task->main; task++) { if (strcmp(test, task->task_name) != 0) { continue; } if (task->is_helper) { continue; } if (process_start(task->task_name, task->process_name, &processes[process_count], 0 /* !is_helper */) == -1) { snprintf(errmsg, sizeof errmsg, "Process `%s` failed to start.", task->process_name); goto out; } main_proc = &processes[process_count]; process_count++; break; } if (main_proc == NULL) { snprintf(errmsg, sizeof errmsg, "No test with that name: %s", test); goto out; } result = process_wait(main_proc, 1, timeout); if (result == -1) { FATAL("process_wait failed"); } else if (result == -2) { /* Don't have to clean up the process, process_wait() has killed it. */ snprintf(errmsg, sizeof errmsg, "timeout"); goto out; } status = process_reap(main_proc); if (status != 0) { snprintf(errmsg, sizeof errmsg, "exit code %d", status); goto out; } if (benchmark_output) { /* Give the helpers time to clean up their act. */ uv_sleep(1000); } out: /* Reap running processes except the main process, it's already dead. */ for (i = 0; i < process_count - 1; i++) { process_terminate(&processes[i]); } if (process_count > 0 && process_wait(processes, process_count - 1, -1) < 0) { FATAL("process_wait failed"); } /* Show error and output from processes if the test failed. */ if (status != 0 || task->show_output) { if (tap_output) { LOGF("not ok %d - %s\n#", test_count, test); } else if (status != 0) { LOGF("\n`%s` failed: %s\n", test, errmsg); } else { LOGF("\n"); } for (i = 0; i < process_count; i++) { switch (process_output_size(&processes[i])) { case -1: LOGF("Output from process `%s`: (unavailable)\n", process_get_name(&processes[i])); break; case 0: LOGF("Output from process `%s`: (no output)\n", process_get_name(&processes[i])); break; default: LOGF("Output from process `%s`:\n", process_get_name(&processes[i])); process_copy_output(&processes[i], fileno(stderr)); break; } } if (!tap_output) { LOG("=============================================================\n"); } /* In benchmark mode show concise output from the main process. */ } else if (benchmark_output) { switch (process_output_size(main_proc)) { case -1: LOGF("%s: (unavailable)\n", test); break; case 0: LOGF("%s: (no output)\n", test); break; default: for (i = 0; i < process_count; i++) { process_copy_output(&processes[i], fileno(stderr)); } break; } } else if (tap_output) { LOGF("ok %d - %s\n", test_count, test); } /* Clean up all process handles. */ for (i = 0; i < process_count; i++) { process_cleanup(&processes[i]); } return status; }
/* * Runs all processes associated with a particular test or benchmark. * It returns 1 if the test succeeded, 0 if it failed. * If the test fails it prints diagnostic information. * If benchmark_output is nonzero, the output from the main process is * always shown. */ int run_task(task_entry_t *test, int timeout, int benchmark_output) { int i, result, success; char errmsg[256]; task_entry_t *helper; int process_count; process_info_t processes[MAX_PROCESSES]; process_info_t *main_process; success = 0; process_count = 0; /* Start all helpers for this test first. */ for (helper = (task_entry_t*)&TASKS; helper->main; helper++) { if (helper->is_helper && strcmp(test->task_name, helper->task_name) == 0) { if (process_start(helper->process_name, &processes[process_count]) == -1) { snprintf((char*)&errmsg, sizeof(errmsg), "process `%s` failed to start.", helper->process_name); goto finalize; } process_count++; } } /* Wait a little bit to allow servers to start. Racy. */ uv_sleep(50); /* Start the main test process. */ if (process_start(test->process_name, &processes[process_count]) == -1) { snprintf((char*)&errmsg, sizeof(errmsg), "process `%s` failed to start.", test->process_name); goto finalize; } main_process = &processes[process_count]; process_count++; /* Wait for the main process to terminate. */ result = process_wait(main_process, 1, timeout); if (result == -1) { FATAL("process_wait failed"); } else if (result == -2) { snprintf((char*)&errmsg, sizeof(errmsg), "timeout."); goto finalize; } /* Reap the main process. */ result = process_reap(main_process); if (result != 0) { snprintf((char*)&errmsg, sizeof(errmsg), "exit code %d.", result); goto finalize; } /* Yes! did it. */ success = 1; finalize: /* Kill all (helper) processes that are still running. */ for (i = 0; i < process_count; i++) { /* If terminate fails the process is probably already closed. */ process_terminate(&processes[i]); } /* Wait until all processes have really terminated. */ if (process_wait((process_info_t*)&processes, process_count, -1) < 0) { FATAL("process_wait failed"); } /* Show error and output from processes if the test failed. */ if (!success) { LOGF("\n`%s` failed: %s\n", test->task_name, errmsg); for (i = 0; i < process_count; i++) { switch (process_output_size(&processes[i])) { case -1: LOGF("Output from process `%s`: (unavailable)\n", process_get_name(&processes[i])); break; case 0: LOGF("Output from process `%s`: (no output)\n", process_get_name(&processes[i])); break; default: LOGF("Output from process `%s`:\n", process_get_name(&processes[i])); process_copy_output(&processes[i], fileno(stderr)); break; } } LOG("=============================================================\n"); /* In benchmark mode show concise output from the main process. */ } else if (benchmark_output) { switch (process_output_size(main_process)) { case -1: LOGF("%s: (unavailabe)\n", test->task_name); break; case 0: LOGF("%s: (no output)\n", test->task_name); break; default: //LOGF("%s: ", test->task_name); process_copy_output(main_process, fileno(stderr)); break; } } /* Clean up all process handles. */ for (i = 0; i < process_count; i++) { process_cleanup(&processes[i]); } return success; }