From ebdc294f10aa206edc8ed3fd4192cdaaef0b0952 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Fri, 7 Mar 2014 12:52:17 +0100 Subject: [PATCH] Add --usage/--help commandline options Change-Id: I22581e04b24bbad6ee587fc93b91a89506fc4f8b Signed-off-by: Aleksander Zdyb --- src/commandline_sdbd.c | 27 ++++++++++++++ src/commandline_sdbd.h | 17 +++++++++ src/sdb.c | 21 ++++++++++- test/test_commandline_sdbd.c | 87 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 142 insertions(+), 10 deletions(-) diff --git a/src/commandline_sdbd.c b/src/commandline_sdbd.c index ccf75f2..f1c3f55 100644 --- a/src/commandline_sdbd.c +++ b/src/commandline_sdbd.c @@ -47,6 +47,8 @@ int parse_sdbd_commandline(SdbdCommandlineArgs *sdbd_args, int argc, char *argv[ { ARG_SENSORS, required_argument, NULL, ARG_S_SENSORS }, { ARG_SDB, required_argument, NULL, ARG_S_SDB }, { ARG_SDBD_LISTEN_PORT, required_argument, NULL, ARG_S_SDBD_LISTEN_PORT }, + { ARG_HELP, no_argument, NULL, ARG_S_HELP }, + { ARG_USAGE, no_argument, NULL, ARG_S_USAGE }, { NULL, 0, NULL, 0 } }; @@ -83,6 +85,10 @@ int parse_sdbd_commandline(SdbdCommandlineArgs *sdbd_args, int argc, char *argv[ return SDBD_COMMANDLINE_FAILURE; } break; + case ARG_S_HELP: + return SDBD_COMMANDLINE_HELP; + case ARG_S_USAGE: + return SDBD_COMMANDLINE_USAGE; case 1: return SDBD_COMMANDLINE_FAILURE_UNKNOWN_OPT; case '?': @@ -140,3 +146,24 @@ void clear_sdbd_commandline_args(SdbdCommandlineArgs *sdbd_args) { memset(sdbd_args, 0, sizeof(SdbdCommandlineArgs)); } + + +void print_sdbd_usage_message(FILE *stream) { + const char *format = "Usage sdbd [OPTION]...\n" + "\t-%c, --%s=HOST:PORT\temulator's name and forward port\n" + "\t-%c, --%s=HOST:PORT\thostname or IP and port of sdb listening on host\n" + "\t-%c, --%s=HOST:PORT \thostname or IP and port of sensors daemon\n" + "\t-%c, --%s=PORT \tport on which sdbd shall be listening on\n" + "\t-%c, --%s \tprint help message\n" + "\t-%c, --%s \tprint this usage message\n" + ; + + fprintf(stream, format, + ARG_S_EMULATOR_VM_NAME, ARG_EMULATOR_VM_NAME, + ARG_S_SDB, ARG_SDB, + ARG_S_SENSORS, ARG_SENSORS, + ARG_S_SDBD_LISTEN_PORT, ARG_SDBD_LISTEN_PORT, + ARG_S_HELP, ARG_HELP, + ARG_S_USAGE, ARG_USAGE + ); +} diff --git a/src/commandline_sdbd.h b/src/commandline_sdbd.h index 9b070ad..598b478 100644 --- a/src/commandline_sdbd.h +++ b/src/commandline_sdbd.h @@ -29,9 +29,17 @@ #define ARG_SENSORS "sensors" #define ARG_S_SENSORS 's' +#define ARG_HELP "help" +#define ARG_S_HELP 'h' + +#define ARG_USAGE "usage" +#define ARG_S_USAGE 'u' + #define SDBD_COMMANDLINE_SUCCESS 0 ///< Success #define SDBD_COMMANDLINE_FAILURE -1 ///< Generic failure #define SDBD_COMMANDLINE_FAILURE_UNKNOWN_OPT -2 ///< Unknown option +#define SDBD_COMMANDLINE_HELP 1 ///< Help request +#define SDBD_COMMANDLINE_USAGE 2 ///< Usage message request /*! * @struct HostPort @@ -53,6 +61,7 @@ typedef struct { int sdbd_port; ///< Port to listen on in tcp mode } SdbdCommandlineArgs; +#include /*! * @fn int parse_sdbd_commandline(SdbdCommandlineArgs *sdbd_args, int argc, char *argv[]) @@ -95,4 +104,12 @@ void apply_sdbd_commandline_defaults(SdbdCommandlineArgs *sdbd_args); */ void clear_sdbd_commandline_args(SdbdCommandlineArgs *sdbd_args); +/*! + * @fn void print_usage_message(FILE *stream) + * @brief Prints usage message to specified \stream + * + * @param stream Stream to print to + */ +void print_sdbd_usage_message(FILE *stream); + #endif /* COMMANDLINE_SDBD_H */ diff --git a/src/sdb.c b/src/sdb.c index 42383d0..d61cdc0 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -1603,6 +1603,25 @@ int main(int argc, char **argv) recovery_mode = 1; } #endif + + apply_sdbd_commandline_defaults(&sdbd_commandline_args); + int parse_ret = parse_sdbd_commandline(&sdbd_commandline_args, argc, argv); + + // TODO: Add detailed error messages + // TODO: Add individual messages for help and usage + if(parse_ret != SDBD_COMMANDLINE_SUCCESS) { + if (parse_ret == SDBD_COMMANDLINE_HELP + || parse_ret == SDBD_COMMANDLINE_USAGE) { + // User requested help or usage + print_sdbd_usage_message(stdout); + return EXIT_SUCCESS; + } + + // Print usage message because of invalid options + print_sdbd_usage_message(stderr); + return EXIT_FAILURE; + } + #if !SDB_HOST if (daemonize() < 0) fatal("daemonize() failed: %.200s", strerror(errno)); @@ -1613,8 +1632,6 @@ int main(int argc, char **argv) //sdbd will never die on emulator! signal(SIGTERM, handle_sig_term); /* tizen specific */ - apply_sdbd_commandline_defaults(&sdbd_commandline_args); - parse_sdbd_commandline(&sdbd_commandline_args, argc, argv); return sdb_main(0, DEFAULT_SDB_PORT); #endif } diff --git a/test/test_commandline_sdbd.c b/test/test_commandline_sdbd.c index 8d332f5..4dd67e8 100644 --- a/test/test_commandline_sdbd.c +++ b/test/test_commandline_sdbd.c @@ -64,6 +64,10 @@ print_nullable((hp)->host), (hp)->port, print_nullable(h), (p))) +#define array_size(a) \ + (sizeof(a) / sizeof((a)[0])) + + void setup(void) { } @@ -73,8 +77,8 @@ void teardown(void) { } -START_TEST(test_ok) { - char *argv[] = { +START_TEST(test_all_opts) { + char *test_argv[] = { "./test", "--emulator=tizen:101", "--listen-port=101", @@ -85,7 +89,7 @@ START_TEST(test_ok) { SdbdCommandlineArgs sdbd_args = {0}; apply_sdbd_commandline_defaults(&sdbd_args); - int parse_res = parse_sdbd_commandline(&sdbd_args, 5, argv); + int parse_res = parse_sdbd_commandline(&sdbd_args, array_size(test_argv), test_argv); if (parse_res != SDBD_COMMANDLINE_SUCCESS) { ck_abort_msg("parsing commandline failed"); @@ -101,13 +105,13 @@ START_TEST(test_ok) { START_TEST(test_empty) { - char *argv[] = { + char *test_argv[] = { "./test" }; SdbdCommandlineArgs sdbd_args = {0}; - int parse_res = parse_sdbd_commandline(&sdbd_args, 1, argv); + int parse_res = parse_sdbd_commandline(&sdbd_args, array_size(test_argv), test_argv); if (parse_res != SDBD_COMMANDLINE_SUCCESS) { ck_abort_msg("parsing commandline failed"); @@ -125,7 +129,7 @@ START_TEST(test_empty) { START_TEST(test_unknown) { - char *argv[] = { + char *test_argv[] = { "./test", "--emulator=tizen:26101", "--unknown=true" @@ -133,7 +137,7 @@ START_TEST(test_unknown) { SdbdCommandlineArgs sdbd_args = {0}; - int parse_res = parse_sdbd_commandline(&sdbd_args, 3, argv); + int parse_res = parse_sdbd_commandline(&sdbd_args, array_size(test_argv), test_argv); if (parse_res != SDBD_COMMANDLINE_FAILURE_UNKNOWN_OPT) { ck_abort_msg("parsing commandline failed"); @@ -181,17 +185,84 @@ START_TEST(test_default_args) { } END_TEST +START_TEST(test_usage_message) { + FILE *stream; + char *buffer = NULL; + size_t buf_len = 0; + + stream = open_memstream(&buffer, &buf_len); + print_sdbd_usage_message(stream); + fclose(stream); + + // Just check if all options are mentioned in usage message + ck_assert(strstr(buffer, "--"ARG_EMULATOR_VM_NAME) != NULL); + ck_assert(strstr(buffer, "--"ARG_SDBD_LISTEN_PORT) != NULL); + ck_assert(strstr(buffer, "--"ARG_SDB) != NULL); + ck_assert(strstr(buffer, "--"ARG_SENSORS) != NULL); + ck_assert(strstr(buffer, "--"ARG_HELP) != NULL); + ck_assert(strstr(buffer, "--"ARG_USAGE) != NULL); + + free(buffer); +} END_TEST + +START_TEST(test_usage) { + char *test_argv[] = { + "./test", + "--usage" + }; + + SdbdCommandlineArgs sdbd_args = {0}; + + int parse_res = parse_sdbd_commandline(&sdbd_args, array_size(test_argv), test_argv); + ck_assert_int_eq(parse_res, SDBD_COMMANDLINE_USAGE); + +} END_TEST + + +START_TEST(test_help) { + char *test_argv[] = { + "./test", + "--help" + }; + + SdbdCommandlineArgs sdbd_args = {0}; + + int parse_res = parse_sdbd_commandline(&sdbd_args, array_size(test_argv), test_argv); + ck_assert_int_eq(parse_res, SDBD_COMMANDLINE_HELP); + +} END_TEST + + +START_TEST(test_help_other_opt) { + char *test_argv[] = { + "./test", + "--listen-port=1234", + "--help" + }; + + SdbdCommandlineArgs sdbd_args = {0}; + + int parse_res = parse_sdbd_commandline(&sdbd_args, array_size(test_argv), test_argv); + ck_assert_int_eq(parse_res, SDBD_COMMANDLINE_HELP); + +} END_TEST + + Suite *sdbd_commandline_suite (void) { Suite *s = suite_create ("sdbd commandline"); TCase *tc_core = tcase_create ("Core"); tcase_add_checked_fixture(tc_core, setup, teardown); - tcase_add_test (tc_core, test_ok); + tcase_add_test (tc_core, test_all_opts); tcase_add_test (tc_core, test_empty); tcase_add_test (tc_core, test_unknown); tcase_add_test (tc_core, test_clear_args); tcase_add_test (tc_core, test_double_clear); tcase_add_test (tc_core, test_default_args); + tcase_add_test (tc_core, test_usage_message); + tcase_add_test (tc_core, test_usage); + tcase_add_test (tc_core, test_help); + tcase_add_test (tc_core, test_help_other_opt); suite_add_tcase (s, tc_core); return s; -- 2.7.4