From e7023612eff5ab8f1be3aaff1b26896962aab139 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 28 May 2015 08:00:14 -0700 Subject: [PATCH] Add a test of cmdline usage strings - and make them saner --- include/grpc/support/cmdline.h | 2 + src/core/support/cmdline.c | 70 +++++++++++++++++++++++--------- test/core/support/cmdline_test.c | 23 +++++++++++ 3 files changed, 75 insertions(+), 20 deletions(-) diff --git a/include/grpc/support/cmdline.h b/include/grpc/support/cmdline.h index c2350a07e8c..e5a266666ee 100644 --- a/include/grpc/support/cmdline.h +++ b/include/grpc/support/cmdline.h @@ -87,6 +87,8 @@ void gpr_cmdline_on_extra_arg( void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv); /* Destroy the parser */ void gpr_cmdline_destroy(gpr_cmdline *cl); +/* Get a string describing usage */ +char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0); #ifdef __cplusplus } diff --git a/src/core/support/cmdline.c b/src/core/support/cmdline.c index 72f46c1bd72..530952c4371 100644 --- a/src/core/support/cmdline.c +++ b/src/core/support/cmdline.c @@ -131,33 +131,63 @@ void gpr_cmdline_on_extra_arg( cl->extra_arg_help = help; } -static void print_usage_and_die(gpr_cmdline *cl) { +/* recursively descend argument list, adding the last element + to s first - so that arguments are added in the order they were + added to the list by api calls */ +static void add_args_to_usage(gpr_strvec *s, arg *a) { + char *tmp; + + if (!a) return; + add_args_to_usage(s, a->next); + + switch (a->type) { + case ARGTYPE_BOOL: + gpr_asprintf(&tmp, " [--%s|--no-%s]", a->name, a->name); + gpr_strvec_add(s, tmp); + break; + case ARGTYPE_STRING: + gpr_asprintf(&tmp, " [--%s=string]", a->name); + gpr_strvec_add(s, tmp); + break; + case ARGTYPE_INT: + gpr_asprintf(&tmp, " [--%s=int]", a->name); + gpr_strvec_add(s, tmp); + break; + } +} + +char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0) { /* TODO(ctiller): make this prettier */ - arg *a; - const char *name = strrchr(cl->argv0, '/'); + gpr_strvec s; + char *tmp; + const char *name = strrchr(argv0, '/'); + if (name) { name++; } else { - name = cl->argv0; - } - fprintf(stderr, "Usage: %s", name); - for (a = cl->args; a; a = a->next) { - switch (a->type) { - case ARGTYPE_BOOL: - fprintf(stderr, " [--%s|--no-%s]", a->name, a->name); - break; - case ARGTYPE_STRING: - fprintf(stderr, " [--%s=string]", a->name); - break; - case ARGTYPE_INT: - fprintf(stderr, " [--%s=int]", a->name); - break; - } + name = argv0; } + + gpr_strvec_init(&s); + + gpr_asprintf(&tmp, "Usage: %s", name); + gpr_strvec_add(&s, tmp); + add_args_to_usage(&s, cl->args); if (cl->extra_arg) { - fprintf(stderr, " [%s...]", cl->extra_arg_name); + gpr_asprintf(&tmp, " [%s...]", cl->extra_arg_name); + gpr_strvec_add(&s, tmp); } - fprintf(stderr, "\n"); + gpr_strvec_add(&s, gpr_strdup("\n")); + + tmp = gpr_strvec_flatten(&s, NULL); + gpr_strvec_destroy(&s); + return tmp; +} + +static void print_usage_and_die(gpr_cmdline *cl) { + char *usage = gpr_cmdline_usage_string(cl, cl->argv0); + fprintf(stderr, "%s", usage); + gpr_free(usage); exit(1); } diff --git a/test/core/support/cmdline_test.c b/test/core/support/cmdline_test.c index a7767ace5e8..26153b192cb 100644 --- a/test/core/support/cmdline_test.c +++ b/test/core/support/cmdline_test.c @@ -35,6 +35,7 @@ #include +#include #include #include #include "test/core/util/test_config.h" @@ -272,6 +273,27 @@ static void test_many(void) { gpr_cmdline_destroy(cl); } +static void test_usage(void) { + gpr_cmdline *cl; + char *usage; + + char *str = NULL; + int x = 0; + int flag = 2; + + cl = gpr_cmdline_create(NULL); + gpr_cmdline_add_string(cl, "str", NULL, &str); + gpr_cmdline_add_int(cl, "x", NULL, &x); + gpr_cmdline_add_flag(cl, "flag", NULL, &flag); + + usage = gpr_cmdline_usage_string(cl, "test"); + GPR_ASSERT(0 == strcmp(usage, + "Usage: test [--str=string] [--x=int] [--flag|--no-flag]\n")); + gpr_free(usage); + + gpr_cmdline_destroy(cl); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_simple_int(); @@ -289,5 +311,6 @@ int main(int argc, char **argv) { test_flag_val_true(); test_flag_val_false(); test_many(); + test_usage(); return 0; }