diff --git a/src/fish_test_helper.cpp b/src/fish_test_helper.cpp index 9ba502dc9..51c63a7a3 100644 --- a/src/fish_test_helper.cpp +++ b/src/fish_test_helper.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -34,7 +35,7 @@ static void report_foreground() { } static void sigint_parent() { - // SIGINT the parent after 1 second, then exit + // SIGINT the parent after a time, then exit int parent = getppid(); usleep(1000000 / 4); //.25 secs kill(parent, SIGINT); @@ -67,26 +68,67 @@ static void print_fds() { fputc('\n', stdout); } +static void show_help(); + +/// A thing that fish_test_helper can do. +struct fth_command_t { + /// The argument to match against. + const char *arg; + + /// Function to invoke. + void (*func)(); + + /// Description of what this does. + const char *desc; +}; + +static fth_command_t s_commands[] = { + {"become_foreground_then_print_stderr", become_foreground_then_print_stderr, + "Claim the terminal (tcsetpgrp) and then print to stderr"}, + {"report_foreground", report_foreground, + "Continually report to stderr whether we own the terminal"}, + {"sigint_parent", sigint_parent, "Wait .25 seconds, then SIGINT the parent process"}, + {"print_stdout_stderr", print_stdout_stderr, "Print 'stdout' to stdout and 'stderr' to stderr"}, + {"print_pid_then_sleep", print_pid_then_sleep, "Print our pid, then sleep for .5 seconds"}, + {"print_pgrp", print_pgrp, "Print our pgroup to stdout"}, + {"print_fds", print_fds, "Print the list of active FDs to stdout"}, + {"help", show_help, "Print list of fish_test_helper commands"}, +}; + +static void show_help() { + printf("fish_test_helper: helper utility for fish\n\n"); + printf("Commands\n"); + printf("--------\n"); + for (const auto &cmd : s_commands) { + printf(" %s:\n %s\n\n", cmd.arg, cmd.desc); + } +} + int main(int argc, char *argv[]) { + std::sort(std::begin(s_commands), std::end(s_commands), + [](const fth_command_t &lhs, const fth_command_t &rhs) { + return strcmp(lhs.arg, rhs.arg) < 0; + }); + if (argc <= 1) { fprintf(stderr, "No commands given.\n"); return 0; } for (int i = 1; i < argc; i++) { - if (!strcmp(argv[i], "become_foreground_then_print_stderr")) { - become_foreground_then_print_stderr(); - } else if (!strcmp(argv[i], "report_foreground")) { - report_foreground(); - } else if (!strcmp(argv[i], "sigint_parent")) { - sigint_parent(); - } else if (!strcmp(argv[i], "print_stdout_stderr")) { - print_stdout_stderr(); - } else if (!strcmp(argv[i], "print_pid_then_sleep")) { - print_pid_then_sleep(); - } else if (!strcmp(argv[i], "print_pgrp")) { - print_pgrp(); - } else if (!strcmp(argv[i], "print_fds")) { - print_fds(); + if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "help") || !strcmp(argv[i], "-h")) { + show_help(); + return 0; + } + + const fth_command_t *found = nullptr; + for (const auto &cmd : s_commands) { + if (!strcmp(argv[i], cmd.arg)) { + found = &cmd; + break; + } + } + if (found) { + found->func(); } else { fprintf(stderr, "%s: Unknown command: %s\n", argv[0], argv[i]); return EXIT_FAILURE;