Add cmdline tests

pull/4391/head
Craig Tiller 9 years ago
parent 81e4e8dd0b
commit 1fa1ab84c9
  1. 8
      include/grpc/support/cmdline.h
  2. 62
      src/core/support/cmdline.c
  3. 187
      test/core/support/cmdline_test.c

@ -83,8 +83,12 @@ void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help,
void gpr_cmdline_on_extra_arg(
gpr_cmdline *cl, const char *name, const char *help,
void (*on_extra_arg)(void *user_data, const char *arg), void *user_data);
/* Parse the command line */
void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv);
/* Enable surviving failure: default behavior is to exit the process */
void gpr_cmdline_set_survive_failure(gpr_cmdline *cl);
/* Parse the command line; returns 1 on success, on failure either dies
(by default) or returns 0 if gpr_cmdline_set_survive_failure() has been
called */
int 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 */

@ -62,11 +62,13 @@ struct gpr_cmdline {
void (*extra_arg)(void *user_data, const char *arg);
void *extra_arg_user_data;
void (*state)(gpr_cmdline *cl, char *arg);
int (*state)(gpr_cmdline *cl, char *arg);
arg *cur_arg;
int survive_failure;
};
static void normal_state(gpr_cmdline *cl, char *arg);
static int normal_state(gpr_cmdline *cl, char *arg);
gpr_cmdline *gpr_cmdline_create(const char *description) {
gpr_cmdline *cl = gpr_malloc(sizeof(gpr_cmdline));
@ -78,6 +80,10 @@ gpr_cmdline *gpr_cmdline_create(const char *description) {
return cl;
}
void gpr_cmdline_set_survive_failure(gpr_cmdline *cl) {
cl->survive_failure = 1;
}
void gpr_cmdline_destroy(gpr_cmdline *cl) {
while (cl->args) {
arg *a = cl->args;
@ -185,16 +191,22 @@ char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0) {
return tmp;
}
static void print_usage_and_die(gpr_cmdline *cl) {
static int 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);
if (!cl->survive_failure) {
exit(1);
}
return 0;
}
static void extra_state(gpr_cmdline *cl, char *str) {
if (!cl->extra_arg) print_usage_and_die(cl);
static int extra_state(gpr_cmdline *cl, char *str) {
if (!cl->extra_arg) {
return print_usage_and_die(cl);
}
cl->extra_arg(cl->extra_arg_user_data, str);
return 1;
}
static arg *find_arg(gpr_cmdline *cl, char *name) {
@ -208,13 +220,13 @@ static arg *find_arg(gpr_cmdline *cl, char *name) {
if (!a) {
fprintf(stderr, "Unknown argument: %s\n", name);
print_usage_and_die(cl);
return NULL;
}
return a;
}
static void value_state(gpr_cmdline *cl, char *str) {
static int value_state(gpr_cmdline *cl, char *str) {
long intval;
char *end;
@ -226,7 +238,7 @@ static void value_state(gpr_cmdline *cl, char *str) {
if (*end || intval < INT_MIN || intval > INT_MAX) {
fprintf(stderr, "expected integer, got '%s' for %s\n", str,
cl->cur_arg->name);
print_usage_and_die(cl);
return print_usage_and_die(cl);
}
*(int *)cl->cur_arg->value = (int)intval;
break;
@ -238,7 +250,7 @@ static void value_state(gpr_cmdline *cl, char *str) {
} else {
fprintf(stderr, "expected boolean, got '%s' for %s\n", str,
cl->cur_arg->name);
print_usage_and_die(cl);
return print_usage_and_die(cl);
}
break;
case ARGTYPE_STRING:
@ -247,16 +259,18 @@ static void value_state(gpr_cmdline *cl, char *str) {
}
cl->state = normal_state;
return 1;
}
static void normal_state(gpr_cmdline *cl, char *str) {
static int normal_state(gpr_cmdline *cl, char *str) {
char *eq = NULL;
char *tmp = NULL;
char *arg_name = NULL;
int r = 1;
if (0 == strcmp(str, "-help") || 0 == strcmp(str, "--help") ||
0 == strcmp(str, "-h")) {
print_usage_and_die(cl);
return print_usage_and_die(cl);
}
cl->cur_arg = NULL;
@ -266,7 +280,7 @@ static void normal_state(gpr_cmdline *cl, char *str) {
if (str[2] == 0) {
/* handle '--' to move to just extra args */
cl->state = extra_state;
return;
return 1;
}
str += 2;
} else {
@ -277,12 +291,15 @@ static void normal_state(gpr_cmdline *cl, char *str) {
/* str is of the form '--no-foo' - it's a flag disable */
str += 3;
cl->cur_arg = find_arg(cl, str);
if (cl->cur_arg == NULL) {
return print_usage_and_die(cl);
}
if (cl->cur_arg->type != ARGTYPE_BOOL) {
fprintf(stderr, "%s is not a flag argument\n", str);
print_usage_and_die(cl);
return print_usage_and_die(cl);
}
*(int *)cl->cur_arg->value = 0;
return; /* early out */
return 1; /* early out */
}
eq = strchr(str, '=');
if (eq != NULL) {
@ -294,9 +311,12 @@ static void normal_state(gpr_cmdline *cl, char *str) {
arg_name = str;
}
cl->cur_arg = find_arg(cl, arg_name);
if (cl->cur_arg == NULL) {
return print_usage_and_die(cl);
}
if (eq != NULL) {
/* str was of the type --foo=value, parse the value */
value_state(cl, eq + 1);
r = value_state(cl, eq + 1);
} else if (cl->cur_arg->type != ARGTYPE_BOOL) {
/* flag types don't have a '--foo value' variant, other types do */
cl->state = value_state;
@ -305,19 +325,23 @@ static void normal_state(gpr_cmdline *cl, char *str) {
*(int *)cl->cur_arg->value = 1;
}
} else {
extra_state(cl, str);
r = extra_state(cl, str);
}
gpr_free(tmp);
return r;
}
void gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) {
int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) {
int i;
GPR_ASSERT(argc >= 1);
cl->argv0 = argv[0];
for (i = 1; i < argc; i++) {
cl->state(cl, argv[i]);
if (!cl->state(cl, argv[i])) {
return 0;
}
}
return 1;
}

@ -40,7 +40,7 @@
#include <grpc/support/useful.h>
#include "test/core/util/test_config.h"
#define LOG_TEST() gpr_log(GPR_INFO, "%s", __FILE__)
#define LOG_TEST() gpr_log(GPR_INFO, "test at %s:%d", __FILE__, __LINE__)
static void test_simple_int(void) {
int x = 1;
@ -273,6 +273,44 @@ static void test_many(void) {
gpr_cmdline_destroy(cl);
}
static void extra_arg_cb(void *user_data, const char *arg) {
int *count = user_data;
GPR_ASSERT(arg != NULL);
GPR_ASSERT(strlen(arg) == 1);
GPR_ASSERT(arg[0] == 'a' + *count);
++*count;
}
static void test_extra(void) {
gpr_cmdline *cl;
int count = 0;
char *args[] = {(char *)__FILE__, "a", "b", "c"};
LOG_TEST();
cl = gpr_cmdline_create(NULL);
gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
&count);
gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args);
GPR_ASSERT(count == 3);
gpr_cmdline_destroy(cl);
}
static void test_extra_dashdash(void) {
gpr_cmdline *cl;
int count = 0;
char *args[] = {(char *)__FILE__, "--", "a", "b", "c"};
LOG_TEST();
cl = gpr_cmdline_create(NULL);
gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
&count);
gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(args), args);
GPR_ASSERT(count == 3);
gpr_cmdline_destroy(cl);
}
static void test_usage(void) {
gpr_cmdline *cl;
char *usage;
@ -281,20 +319,154 @@ static void test_usage(void) {
int x = 0;
int flag = 2;
LOG_TEST();
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);
gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
NULL);
usage = gpr_cmdline_usage_string(cl, "test");
GPR_ASSERT(
0 == strcmp(usage,
"Usage: test [--str=string] [--x=int] [--flag|--no-flag]\n"));
GPR_ASSERT(0 == strcmp(usage,
"Usage: test [--str=string] [--x=int] "
"[--flag|--no-flag] [file...]\n"));
gpr_free(usage);
usage = gpr_cmdline_usage_string(cl, "/foo/test");
GPR_ASSERT(0 == strcmp(usage,
"Usage: test [--str=string] [--x=int] "
"[--flag|--no-flag] [file...]\n"));
gpr_free(usage);
gpr_cmdline_destroy(cl);
}
static void test_help(void) {
gpr_cmdline *cl;
char *str = NULL;
int x = 0;
int flag = 2;
char *help[] = {(char *)__FILE__, "-h"};
LOG_TEST();
cl = gpr_cmdline_create(NULL);
gpr_cmdline_set_survive_failure(cl);
gpr_cmdline_add_string(cl, "str", NULL, &str);
gpr_cmdline_add_int(cl, "x", NULL, &x);
gpr_cmdline_add_flag(cl, "flag", NULL, &flag);
gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
NULL);
GPR_ASSERT(0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(help), help));
gpr_cmdline_destroy(cl);
}
static void test_badargs1(void) {
gpr_cmdline *cl;
char *str = NULL;
int x = 0;
int flag = 2;
char *bad_arg_name[] = {(char *)__FILE__, "--y"};
LOG_TEST();
cl = gpr_cmdline_create(NULL);
gpr_cmdline_set_survive_failure(cl);
gpr_cmdline_add_string(cl, "str", NULL, &str);
gpr_cmdline_add_int(cl, "x", NULL, &x);
gpr_cmdline_add_flag(cl, "flag", NULL, &flag);
gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
NULL);
GPR_ASSERT(0 ==
gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_arg_name), bad_arg_name));
gpr_cmdline_destroy(cl);
}
static void test_badargs2(void) {
gpr_cmdline *cl;
char *str = NULL;
int x = 0;
int flag = 2;
char *bad_int_value[] = {(char *)__FILE__, "--x", "henry"};
LOG_TEST();
cl = gpr_cmdline_create(NULL);
gpr_cmdline_set_survive_failure(cl);
gpr_cmdline_add_string(cl, "str", NULL, &str);
gpr_cmdline_add_int(cl, "x", NULL, &x);
gpr_cmdline_add_flag(cl, "flag", NULL, &flag);
gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
NULL);
GPR_ASSERT(
0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_int_value), bad_int_value));
gpr_cmdline_destroy(cl);
}
static void test_badargs3(void) {
gpr_cmdline *cl;
char *str = NULL;
int x = 0;
int flag = 2;
char *bad_bool_value[] = {(char *)__FILE__, "--flag=henry"};
LOG_TEST();
cl = gpr_cmdline_create(NULL);
gpr_cmdline_set_survive_failure(cl);
gpr_cmdline_add_string(cl, "str", NULL, &str);
gpr_cmdline_add_int(cl, "x", NULL, &x);
gpr_cmdline_add_flag(cl, "flag", NULL, &flag);
gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
NULL);
GPR_ASSERT(0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_bool_value),
bad_bool_value));
gpr_cmdline_destroy(cl);
}
static void test_badargs4(void) {
gpr_cmdline *cl;
char *str = NULL;
int x = 0;
int flag = 2;
char *bad_bool_value[] = {(char *)__FILE__, "--no-str"};
LOG_TEST();
cl = gpr_cmdline_create(NULL);
gpr_cmdline_set_survive_failure(cl);
gpr_cmdline_add_string(cl, "str", NULL, &str);
gpr_cmdline_add_int(cl, "x", NULL, &x);
gpr_cmdline_add_flag(cl, "flag", NULL, &flag);
gpr_cmdline_on_extra_arg(cl, "file", "filenames to process", extra_arg_cb,
NULL);
GPR_ASSERT(0 == gpr_cmdline_parse(cl, GPR_ARRAY_SIZE(bad_bool_value),
bad_bool_value));
gpr_cmdline_destroy(cl);
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_simple_int();
@ -312,6 +484,13 @@ int main(int argc, char **argv) {
test_flag_val_true();
test_flag_val_false();
test_many();
test_extra();
test_extra_dashdash();
test_usage();
test_help();
test_badargs1();
test_badargs2();
test_badargs3();
test_badargs4();
return 0;
}

Loading…
Cancel
Save