From: Michael D. Lowis Date: Fri, 3 Oct 2014 19:31:02 +0000 (-0400) Subject: revised interface for parsing X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=29e61bcb6464fed2905fcf763c69ab9130c99969;p=projs%2Fopts.git revised interface for parsing --- diff --git a/Rakefile b/Rakefile index 5885867..3e07f2c 100644 --- a/Rakefile +++ b/Rakefile @@ -25,6 +25,8 @@ TestEnv = Env.clone do |env| env.build_dir('source','build/obj/test_source') env.build_dir('tests','build/obj/tests/source') env['CPPPATH'] += Dir['tests/'] + env["CFLAGS"] += ['--coverage'] + env["LDFLAGS"] += ['--coverage'] end # Make sure the environment is processed before we quit diff --git a/source/opts.c b/source/opts.c old mode 100644 new mode 100755 index 42e74c1..a6e2079 --- a/source/opts.c +++ b/source/opts.c @@ -3,155 +3,162 @@ #include #include "opts.h" +typedef struct { + char* name; + char* tag; + char* value; +} option_t; + +typedef struct entry_t { + void* value; + struct entry_t* next; +} entry_t; + +static entry_t* Options = NULL; +static entry_t* Arguments = NULL; + +typedef enum { LONG, SHORT } OptionType_T; + +typedef struct { + unsigned int line_idx; + unsigned int col_idx; + unsigned int arg_count; + char** arg_vect; + int current; + OptionConfig_T* options; +} StreamContext_T; + +static void opts_init_context( StreamContext_T* ctx, int argc, char** argv ); +static void opts_parse_short_option( StreamContext_T* ctx ); +static void opts_parse_long_option( StreamContext_T* ctx ); +static char* opts_parse_optarg(StreamContext_T* ctx, char* opt_name); +static void opts_parse_argument( StreamContext_T* ctx ); +static void opts_parse_error(const char* msg, const char* opt_name); + +static OptionConfig_T* opts_get_option_config( OptionConfig_T* opts, OptionType_T typ, char* name ); +static char* opts_next_token( StreamContext_T* ctx ); +static void opts_consume_ws( StreamContext_T* ctx ); +static char opts_next_char( StreamContext_T* ctx ); +static char* opts_append_char( char* str, char ch ); static char* strclone(const char* p_old); -Result_T* OPTS_ParseOptions( OptionConfig_T* opts, int argc, char** argv ) -{ - // Setup the stream +static void opts_add_option(char* name, char* tag, char* arg); +static void opts_add_argument(char* arg); + +void opts_parse( OptionConfig_T* opts, int argc, char** argv ) { + /* Setup the stream */ StreamContext_T ctx; ctx.options = opts; - OPTS_InitContext( &ctx, argc, argv ); - - // Until we run out of characters - while( ctx.current != EOF ) - { - OPTS_ConsumeWhitespace( &ctx ); - - // If we have an option - if ( '-' == ctx.current ) - { - // And it's a long one - if( '-' == OPTS_NextCharacter( &ctx ) ) - { - // Consume the second '-' - OPTS_NextCharacter( &ctx ); - - // Parse the option - OPTS_ParseLongOption( &ctx ); - } - // Or a short one - else - { - // Parse the option - OPTS_ParseShortOption( &ctx ); + opts_init_context( &ctx, argc, argv ); + + /* Until we run out of characters */ + while (ctx.current != EOF) { + opts_consume_ws( &ctx ); + /* If we have an option */ + if ('-' == ctx.current) { + /* And it's a long one */ + if ('-' == opts_next_char( &ctx )) { + /* Consume the second '-' */ + opts_next_char( &ctx ); + /* Parse the option */ + opts_parse_long_option( &ctx ); + } else { + /* Parse the option */ + opts_parse_short_option( &ctx ); } - } - // Or we have a floating argument - else - { - OPTS_ParseArgument( &ctx ); + } else { + opts_parse_argument( &ctx ); } } +} - return ctx.results; +void opts_reset(void) { + while (Options != NULL) { + entry_t* entry = Options; + option_t* opt = (option_t*)entry->value; + Options = entry->next; + free(opt->name); + free(opt->tag); + if(opt->name != opt->value) + free(opt->value); + free(opt); + free(entry); + } + + while (Arguments != NULL) { + entry_t* entry = Arguments; + char* arg = (char*)entry->value; + Arguments = entry->next; + free(arg); + free(entry); + } } -void OPTS_InitContext( StreamContext_T* ctx, int argc, char** argv ) -{ +static void opts_init_context( StreamContext_T* ctx, int argc, char** argv ) { // Setup the char stream ctx->line_idx = 0; ctx->col_idx = -1; ctx->arg_count = argc; ctx->arg_vect = argv; - (void)OPTS_NextCharacter( ctx ); // Loads up the first char - - // Setup the results object - ctx->results = (Result_T*)malloc( sizeof( Result_T ) ); - ctx->results->options = (OptionList_T*)malloc( sizeof( OptionList_T ) ); - ctx->results->options->head = NULL; - ctx->results->options->tail = NULL; - ctx->results->arguments = (ArgumentList_T*)malloc( sizeof( ArgumentList_T ) ); - ctx->results->arguments->head = NULL; - ctx->results->arguments->tail = NULL; + (void)opts_next_char( ctx ); // Loads up the first char } -void OPTS_ParseShortOption( StreamContext_T* ctx ) -{ +static void opts_parse_short_option( StreamContext_T* ctx ) { // Get Config char opt_name[2] = { ctx->current, '\0' }; - OptionConfig_T* config = OPTS_GetOptConfig( ctx->options, SHORT, opt_name ); - if( config != NULL ) - { + OptionConfig_T* config = opts_get_option_config( ctx->options, SHORT, opt_name ); + if (config != NULL) { char* opt_arg = NULL; - (void)OPTS_NextCharacter( ctx ); - if( 1 == config->has_arg ) - { - OPTS_ConsumeWhitespace( ctx ); - if( ('-' == ctx->current) || (EOF == ctx->current) ) - { - printf("Expected an argument for option '%s'\n", opt_name); - exit(1); - } - opt_arg = OPTS_NextToken( ctx ); - } - else if( (' ' != ctx->current) && (EOF != ctx->current) ) - { - OPTS_ParseShortOption( ctx ); - } - OPTS_AddOption( ctx->results, opt_name, opt_arg ); - } - else - { - printf("Unknown Option '%s'\n", opt_name); - exit(1); + (void)opts_next_char( ctx ); + if (config->has_arg) + opt_arg = opts_parse_optarg( ctx, opt_name ); + else if ((' ' != ctx->current) && (EOF != ctx->current)) + opts_parse_short_option( ctx ); + opts_add_option( strclone(opt_name), config->tag, opt_arg ); + } else { + opts_parse_error("Unknown Option", opt_name); } } -void OPTS_ParseLongOption( StreamContext_T* ctx ) -{ - char* opt_name = OPTS_NextToken( ctx ); - OptionConfig_T* config = OPTS_GetOptConfig( ctx->options, LONG, opt_name ); - if( config != NULL ) - { +static void opts_parse_long_option( StreamContext_T* ctx ) { + char* opt_name = opts_next_token( ctx ); + OptionConfig_T* config = opts_get_option_config( ctx->options, LONG, opt_name ); + if (config != NULL) { char* opt_arg = NULL; - if( 1 == config->has_arg ) - { - OPTS_ConsumeWhitespace( ctx ); - if( ('-' == ctx->current) || (EOF == ctx->current) ) - { - printf("Expected an argument for option '%s'\n", opt_name); - exit(1); - } - opt_arg = OPTS_NextToken( ctx ); - } - OPTS_AddOption( ctx->results, opt_name, opt_arg ); - } - else - { - printf("Unknown Option '%s'\n", opt_name); - exit(1); + if (config->has_arg) + opt_arg = opts_parse_optarg( ctx, opt_name ); + opts_add_option( opt_name, config->tag, opt_arg ); + } else { + opts_parse_error("Unknown Option", opt_name); } } -void OPTS_ParseArgument( StreamContext_T* ctx ) -{ - char* arg_val = OPTS_NextToken( ctx ); - if( NULL != arg_val ) - { - Argument_T* arg = (Argument_T*)malloc( sizeof( Argument_T ) ); - arg->val = arg_val; - arg->next = NULL; - if( ctx->results->arguments->head == NULL ) - { - ctx->results->arguments->head = arg; - ctx->results->arguments->tail = arg; - } - else - { - ctx->results->arguments->tail->next = arg; - ctx->results->arguments->tail = arg; - } - } +static char* opts_parse_optarg(StreamContext_T* ctx, char* opt_name) { + opts_consume_ws( ctx ); + if (('-' == ctx->current) || (EOF == ctx->current)) + opts_parse_error("Expected an argument, none received", opt_name); + return opts_next_token( ctx ); } -OptionConfig_T* OPTS_GetOptConfig( OptionConfig_T* opts, OptionType_T typ, char* name ) -{ +static void opts_parse_error(const char* msg, const char* opt_name) { + fprintf(stderr, "Option '%s' : %s\n", opt_name, msg); + exit(1); +} + +static void opts_parse_argument( StreamContext_T* ctx ) { + char* arg_val = opts_next_token( ctx ); + if (NULL != arg_val) + opts_add_argument(arg_val); +} + + + +static OptionConfig_T* opts_get_option_config( OptionConfig_T* opts, OptionType_T type, char* name ) { OptionConfig_T* cfg = NULL; int i = 0; - while( opts[i].type != END ) - { - if( (opts[i].type == typ) && (0 == strcmp(opts[i].name, name)) ) - { + while( opts[i].name != NULL ) { + OptionType_T curr_type = (strlen(opts[i].name) > 1) ? LONG : SHORT; + if ((curr_type == type) && (0 == strcmp(opts[i].name, name))) { cfg = &(opts[i]); break; } @@ -160,90 +167,55 @@ OptionConfig_T* OPTS_GetOptConfig( OptionConfig_T* opts, OptionType_T typ, char* return cfg; } -char* OPTS_NextToken( StreamContext_T* ctx ) -{ +static char* opts_next_token( StreamContext_T* ctx ) { char* tok = NULL; - OPTS_ConsumeWhitespace( ctx ); - if ( EOF != ctx->current ) - { + opts_consume_ws( ctx ); + if (EOF != ctx->current) { // Setup the string tok = (char*)malloc(2); tok[0] = ctx->current; tok[1] = '\0'; - (void)OPTS_NextCharacter( ctx ); - while( (EOF != ctx->current) && (' ' != ctx->current) ) - { - tok = OPTS_AppendCharacter( tok, ctx->current ); - (void)OPTS_NextCharacter( ctx ); + (void)opts_next_char( ctx ); + while ((EOF != ctx->current) && (' ' != ctx->current)) { + tok = opts_append_char( tok, ctx->current ); + (void)opts_next_char( ctx ); } } return tok; } -void OPTS_AddOption( Result_T* res, char* name, char* arg ) -{ - if( (NULL != res) && (NULL != res->options) ) - { - Option_T* opt = (Option_T*)malloc( sizeof( Option_T ) ); - opt->key = strclone( name ); - opt->val = arg; - opt->next = NULL; - if( res->options->head == NULL ) - { - res->options->head = opt; - res->options->tail = opt; - } - else - { - res->options->tail->next = opt; - res->options->tail = opt; - } - } -} - -void OPTS_ConsumeWhitespace( StreamContext_T* ctx ) -{ - while( ' ' == ctx->current ) - { - (void)OPTS_NextCharacter( ctx ); - } +static void opts_consume_ws( StreamContext_T* ctx ) { + while (' ' == ctx->current) + (void)opts_next_char( ctx ); } -#include -char OPTS_NextCharacter( StreamContext_T* ctx ) -{ +static char opts_next_char( StreamContext_T* ctx ) { char current = EOF; ctx->current = EOF; - if( ctx->line_idx < ctx->arg_count ) - { + if (ctx->line_idx < ctx->arg_count) { ctx->col_idx++; - - if( ctx->line_idx < ctx->arg_count ) - { + if (ctx->line_idx < ctx->arg_count) { char temp = ctx->arg_vect[ ctx->line_idx ][ ctx->col_idx ]; - if( temp == '\0' ) - { + if (temp == '\0') { ctx->col_idx = -1; ctx->line_idx++; current = ' '; ctx->current = current; - } - else - { + } else { temp = (temp == '=') ? ' ' : temp; current = temp; ctx->current = current; } } } + return current; } -char* OPTS_AppendCharacter( char* str, char ch ) -{ +static char* opts_append_char( char* str, char ch ) { unsigned int new_size = strlen( str ) + 2; str = (char*)realloc( str, new_size ); str[ new_size - 2 ] = ch; @@ -251,7 +223,6 @@ char* OPTS_AppendCharacter( char* str, char ch ) return str; } - static char* strclone(const char* p_old) { size_t length = strlen(p_old); char* p_str = (char*)malloc(length+1); @@ -260,3 +231,61 @@ static char* strclone(const char* p_old) { return p_str; } +/*****************************************************************************/ + +static void opts_add_option(char* name, char* tag, char* arg) { + option_t* option = (option_t*)malloc(sizeof(option_t)); + option->name = name; + option->tag = strclone(tag); + option->value = (NULL == arg) ? name : arg; + entry_t* entry = (entry_t*)malloc(sizeof(entry_t)); + entry->value = (void*)option; + entry->next = Options; + Options = entry; +} + +static void opts_add_argument(char* arg_val) { + entry_t* entry = (entry_t*)malloc(sizeof(entry_t)); + entry->value = (void*)arg_val; + entry->next = Arguments; + Arguments = entry; +} + +/*****************************************************************************/ +option_t* find_option(const char* name, const char* tag) { + option_t* p_opt = NULL; + entry_t* current = Options; + while (current != NULL) { + option_t* curr_opt = (option_t*)current->value; + if (((NULL == name) || (0 == strcmp(name, curr_opt->name))) && + ((NULL == tag) || (0 == strcmp(tag, curr_opt->tag)))) { + p_opt = curr_opt; + break; + } + current = current->next; + } + return p_opt; +} + +bool opts_is_set(const char* name, const char* tag) +{ + return (NULL != find_option(name,tag)); +} + +const char* opts_get_value(const char* name, const char* tag) +{ + option_t* p_opt = find_option(name,tag); + return (NULL == p_opt) ? NULL : p_opt->value; +} + +size_t opts_num_args(void) +{ + return 0; +} + +const char* opts_get_arg(size_t index) +{ + (void)index; + return NULL; +} + diff --git a/source/opts.h b/source/opts.h old mode 100644 new mode 100755 index 3f8571e..b2233d0 --- a/source/opts.h +++ b/source/opts.h @@ -1,81 +1,31 @@ #ifndef OPTS_H #define OPTS_H -typedef struct Option_T { - char* key; - char* val; - struct Option_T* next; -} Option_T; - -typedef struct OptionList { - Option_T* head; - Option_T* tail; -} OptionList_T; - -typedef struct Argument_T { - char* val; - struct Argument_T* next; -} Argument_T; - -typedef struct ArgumentList { - Argument_T* head; - Argument_T* tail; -} ArgumentList_T; - -typedef struct Result_T { - ArgumentList_T* arguments; - OptionList_T* options; -} Result_T; +#ifdef __cplusplus +extern "C" { +#endif -typedef enum { - LONG, - SHORT, - END -} OptionType_T; +#include +#include typedef struct OptionConfig_T { - unsigned int type; char* name; - char* dest; - int has_arg; + bool has_arg; + char* tag; char* desc; } OptionConfig_T; -typedef struct { - unsigned int line_idx; - unsigned int col_idx; - unsigned int arg_count; - char** arg_vect; - char current; - OptionConfig_T* options; - Result_T* results; -} StreamContext_T; - -#ifdef __cplusplus -extern "C" { -#endif - -Result_T* OPTS_ParseOptions( OptionConfig_T* opts, int argc, char** argv ); - -void OPTS_InitContext( StreamContext_T* ctx, int argc, char** argv ); - -void OPTS_ParseShortOption( StreamContext_T* ctx ); - -void OPTS_ParseLongOption( StreamContext_T* ctx ); - -void OPTS_ParseArgument( StreamContext_T* ctx ); - -OptionConfig_T* OPTS_GetOptConfig( OptionConfig_T* opts, OptionType_T typ, char* name ); +void opts_parse( OptionConfig_T* opts, int argc, char** argv ); -char* OPTS_NextToken( StreamContext_T* ctx ); +void opts_reset(void); -void OPTS_AddOption( Result_T* res, char* name, char* arg ); +bool opts_is_set(const char* name, const char* tag); -void OPTS_ConsumeWhitespace( StreamContext_T* ctx ); +const char* opts_get_value(const char* name, const char* tag); -char OPTS_NextCharacter( StreamContext_T* ctx ); +size_t opts_num_args(void); -char* OPTS_AppendCharacter( char* str, char ch ); +const char* opts_get_arg(size_t index); #ifdef __cplusplus } diff --git a/tests/atf.c b/tests/atf.c new file mode 100755 index 0000000..14a972a --- /dev/null +++ b/tests/atf.c @@ -0,0 +1,38 @@ +/** + @file atf.c + @brief See header for details + $Revision$ + $HeadURL$ + */ +#include "atf.h" + +char* Curr_Test = NULL; +static unsigned int Total = 0; +static unsigned int Failed = 0; + +void atf_run_suite(suite_t suite) { + suite(); +} + +void atf_test_start(char* p_test_name) { + Curr_Test = p_test_name; + Total++; +} + +void atf_test_fail(char* expr, char* file, int line) { + Failed++; + printf("%s:%d:0:%s:FAIL\n\t%s\n", file, line, Curr_Test, expr); \ +} + +int atf_print_results(void) { + static const char* results_string = + "\nUnit Test Summary" + "\n-----------------" + "\nTotal: %d" + "\nPassed: %d" + "\nFailed: %d" + "\n\n"; + printf(results_string, Total, Total - Failed, Failed); + return Failed; +} + diff --git a/tests/atf.h b/tests/atf.h new file mode 100755 index 0000000..dc156de --- /dev/null +++ b/tests/atf.h @@ -0,0 +1,40 @@ +/** + @file test.h + @brief TODO: Describe this file + $Revision$ + $HeadURL$ + */ +#ifndef TEST_H +#define TEST_H + +#include + +#define CHECK(expr) \ + if (!(expr)) { atf_test_fail(#expr,__FILE__,__LINE__); break; } + +#define TEST_SUITE(name) void name(void) + +#define TEST(desc) \ + for(atf_test_start(#desc); Curr_Test != NULL; Curr_Test = NULL) + +#define RUN_EXTERN_TEST_SUITE(name) \ + do { extern TEST_SUITE(name); atf_run_suite(&name); } while(0) + +#define RUN_TEST_SUITE(name) \ + do { atf_run_suite(&name) } while(0) + +#define PRINT_TEST_RESULTS atf_print_results + +typedef void (*suite_t)(void); + +extern char* Curr_Test; + +void atf_run_suite(suite_t suite); + +void atf_test_start(char* p_test_name); + +void atf_test_fail(char* expr, char* file, int line); + +int atf_print_results(void); + +#endif /* TEST_H */ diff --git a/tests/main.c b/tests/main.c index 98d6801..c47450f 100755 --- a/tests/main.c +++ b/tests/main.c @@ -1,9 +1,9 @@ -#include "test.h" +#include "atf.h" int main(int argc, char** argv) { (void)argc; (void)argv; - RUN_TEST_SUITE(Opts); + RUN_EXTERN_TEST_SUITE(Opts); return PRINT_TEST_RESULTS(); } diff --git a/tests/test.c b/tests/test.c deleted file mode 100755 index d58c9d4..0000000 --- a/tests/test.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - @file test.c - @brief See header for details - $Revision$ - $HeadURL$ - */ -#include "test.h" - -int Loop_Var; -char* Curr_Test; -test_results_t Test_Results = {0}; - -static const char* Results_String = -"\nUnit Test Summary" -"\n-----------------" -"\nTotal: %d" -"\nPassed: %d" -"\nFailed: %d" -"\n\n" -; - -int test_print_results(void) { - (void)Loop_Var; - (void)Curr_Test; - printf(Results_String, - Test_Results.total, - Test_Results.total - Test_Results.failed, - Test_Results.failed); - return Test_Results.failed; -} - -void test_fail(char* expr, char* file, int line) { - Test_Results.failed++; - printf("%s:%d:0:%s:FAIL\n\t%s\n", file, line, Curr_Test, expr); \ -} - diff --git a/tests/test.h b/tests/test.h deleted file mode 100755 index 4ddfc44..0000000 --- a/tests/test.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - @file test.h - @brief TODO: Describe this file - $Revision$ - $HeadURL$ - */ -#ifndef TEST_H -#define TEST_H - -#include - -#define CHECK(expr) \ - if (!(expr)) { \ - test_fail(#expr,__FILE__,__LINE__-1); \ - break; \ - } - -#define TEST(desc) \ - Curr_Test = #desc; \ - Test_Results.total++; \ - test_setup(); \ - for(Loop_Var = 0; Loop_Var < 1; Loop_Var++) - -#define TEST_SUITE(name) void name(void) - -#define RUN_TEST_SUITE(name) \ - extern TEST_SUITE(name); \ - name(); - -#define PRINT_TEST_RESULTS test_print_results - -typedef struct { - unsigned int total; - unsigned int passed; - unsigned int failed; -} test_results_t; - -extern int Loop_Var; - -extern char* Curr_Test; - -extern test_results_t Test_Results; - -int test_print_results(void); -void test_fail(char* expr, char* file, int line); - -#endif /* TEST_H */ diff --git a/tests/test_opts.c b/tests/test_opts.c old mode 100644 new mode 100755 index 28ddb6c..4be03de --- a/tests/test_opts.c +++ b/tests/test_opts.c @@ -1,5 +1,5 @@ // Unit Test Framework Includes -#include "test.h" +#include "atf.h" #include #include #include @@ -13,11 +13,12 @@ // Sample Option Configuration //----------------------------------------------------------------------------- OptionConfig_T Options_Config[] = { - { SHORT, (char*)"a", (char*)"test_a", 0, (char*)"A simple test option" }, - { SHORT, (char*)"b", (char*)"test_b", 1, (char*)"A simple test option" }, - { LONG, (char*)"foo", (char*)"test_d", 0, (char*)"A simple test option" }, - { LONG, (char*)"bar", (char*)"test_e", 1, (char*)"A simple test option" }, - { END, (char*)NULL, (char*)NULL, 0, (char*)NULL } + { (char*)"a", false, (char*)"test_a", (char*)"A simple test option" }, + { (char*)"b", true, (char*)"test_b", (char*)"A simple test option" }, + { (char*)"c", false, (char*)"test_c", (char*)"A simple test option" }, + { (char*)"foo", false, (char*)"test_d", (char*)"A simple test option" }, + { (char*)"bar", true, (char*)"test_e", (char*)"A simple test option" }, + { (char*)NULL, false, (char*)NULL, (char*)NULL } }; //----------------------------------------------------------------------------- @@ -43,112 +44,18 @@ void test_setup(void) {} // Begin Unit Tests //----------------------------------------------------------------------------- TEST_SUITE(Opts) { - //------------------------------------------------------------------------- - // Test InitContext Function - //------------------------------------------------------------------------- - TEST(Verify_InitContext_Initializes_The_StreamContext) - { - StreamContext_T ctx; - char* args[] = { (char*)"-a", (char*)"b", (char*)"--foo", (char*)"--foo=bar" }; - OPTS_InitContext( &ctx, 4, args ); - - CHECK( 0 == ctx.line_idx ); - CHECK( 0 == ctx.col_idx ); - CHECK( 4 == ctx.arg_count ); - CHECK( args == ctx.arg_vect ); - CHECK( '-' == ctx.current ); - CHECK( NULL != ctx.results ); - CHECK( NULL != ctx.results->options ); - CHECK( NULL == ctx.results->options->head ); - CHECK( NULL == ctx.results->options->tail ); - CHECK( NULL != ctx.results->arguments ); - CHECK( NULL == ctx.results->arguments->head ); - CHECK( NULL == ctx.results->arguments->tail ); - } - //------------------------------------------------------------------------- // Test ParseOptions Function //------------------------------------------------------------------------- - TEST(Verify_ParseOptions_Parses_A_Short_Option_With_No_Param) - { - char* args[] = { (char*)"-a" }; - - CHECK_DOES_NOT_EXIT() - { - Result_T* results = OPTS_ParseOptions( Options_Config, 1, args ); - - OptionList_T* result = results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "a" ) ); - CHECK( NULL == result->tail->val ); - CHECK( NULL == result->tail->next ); - } - } - - TEST(Verify_ParseOptions_Parses_A_Short_Option_With_A_Param_And_A_Space) - { - char* args[] = { (char*)"-b", (char*)"5" }; - - CHECK_DOES_NOT_EXIT() - { - Result_T* results = OPTS_ParseOptions( Options_Config, 2, args ); - - OptionList_T* result = results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "b" ) ); - CHECK( NULL != result->tail->val ); - CHECK( 0 == strcmp( result->tail->val, "5" ) ); - CHECK( NULL == result->tail->next ); - } - } - - TEST(Verify_ParseOptions_Parses_A_Short_Option_With_A_Param_And_No_Space) - { - char* args[] = { (char*)"-b5" }; - - CHECK_DOES_NOT_EXIT() - { - Result_T* results = OPTS_ParseOptions( Options_Config, 1, args ); - - OptionList_T* result = results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "b" ) ); - CHECK( NULL != result->tail->val ); - CHECK( 0 == strcmp( result->tail->val, "5" ) ); - CHECK( NULL == result->tail->next ); - } - } - TEST(Verify_ParseOptions_Parses_A_Long_Option_With_No_Param) { char* args[] = { (char*)"--foo" }; - CHECK_DOES_NOT_EXIT() { - Result_T* results = OPTS_ParseOptions( Options_Config, 1, args ); - - OptionList_T* result = results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "foo" ) ); - CHECK( NULL == result->tail->val ); - CHECK( NULL == result->tail->next ); + opts_parse( Options_Config, 1, args ); + CHECK(opts_is_set("foo", NULL)); } + opts_reset(); } TEST(Verify_ParseOptions_Parses_A_Long_Option_With_A_Param_And_A_Space) @@ -157,657 +64,370 @@ TEST_SUITE(Opts) { CHECK_DOES_NOT_EXIT() { - Result_T* results = OPTS_ParseOptions( Options_Config, 2, args ); - - OptionList_T* result = results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "bar" ) ); - CHECK( NULL != result->tail->val ); - CHECK( 0 == strcmp( result->tail->val, "baz" ) ); - CHECK( NULL == result->tail->next ); + opts_parse( Options_Config, 2, args ); + CHECK(opts_is_set("bar", NULL)); + CHECK(0 == strcmp("baz", opts_get_value("bar", NULL))); } + opts_reset(); } TEST(Verify_ParseOptions_Parses_A_Long_Option_With_A_Param_And_An_Equals_Sign) { char* args[] = { (char*)"--bar=baz" }; - CHECK_DOES_NOT_EXIT() { - Result_T* results = OPTS_ParseOptions( Options_Config, 1, args ); - - OptionList_T* result = results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "bar" ) ); - CHECK( NULL != result->tail->val ); - CHECK( 0 == strcmp( result->tail->val, "baz" ) ); - CHECK( NULL == result->tail->next ); + opts_parse( Options_Config, 1, args ); + CHECK(opts_is_set("bar", NULL)); + CHECK(0 == strcmp("baz", opts_get_value("bar", NULL))); } + opts_reset(); } - TEST(Verify_ParseOptions_Parses_A_Floating_Argument) + TEST(Verify_ParseOptions_Parses_a_long_option_with_a_missing_param) { - char* args[] = { (char*)"baz1" }; + int exit_code = 0; + char* args[] = { (char*)"--bar" }; - CHECK_DOES_NOT_EXIT() - { - Result_T* results = OPTS_ParseOptions( Options_Config, 1, args ); - - ArgumentList_T* result = results->arguments; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( 0 == strcmp( result->tail->val, (char*)"baz1" ) ); - CHECK( NULL == result->tail->next ); + exit_code = setjmp( Exit_Point ); + if( 0 == exit_code ) { + opts_parse( Options_Config, 1, args ); + // If we fail to call exit then this breaks our test + CHECK( false ); + } else { + CHECK( 1 == exit_code ); } + opts_reset(); } - //------------------------------------------------------------------------- - // Test ParseShortOption Function - //------------------------------------------------------------------------- - TEST(Verify_ParseShortOption_Exits_With_Error_On_Invalid_Option) + TEST(Verify_ParseOptions_Parses_a_long_option_with_a_missing_param) { int exit_code = 0; - char* args[] = { (char*)"z" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); + char* args[] = { (char*)"--bar-" }; exit_code = setjmp( Exit_Point ); - if( 0 == exit_code ) - { - OPTS_ParseShortOption( &ctx ); + if( 0 == exit_code ) { + opts_parse( Options_Config, 1, args ); // If we fail to call exit then this breaks our test CHECK( false ); - } - else - { - OptionList_T* result = ctx.results->options; + } else { CHECK( 1 == exit_code ); - CHECK( NULL != result ); - CHECK( NULL == result->head ); - CHECK( NULL == result->tail ); } + opts_reset(); } - TEST(Verify_ParseShortOption_Parses_A_Single_Valid_Option_With_No_Arg) + TEST(Verify_ParseOptions_exits_when_invalid_long_option) { - char* args[] = { (char*)"a", (char*)"a" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 2, args ); + int exit_code = 0; + char* args[] = { (char*)"--baz-" }; - CHECK_DOES_NOT_EXIT() - { - OPTS_ParseShortOption( &ctx ); - OptionList_T* result = ctx.results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "a" ) ); - CHECK( NULL == result->tail->val ); - CHECK( NULL == result->tail->next ); + exit_code = setjmp( Exit_Point ); + if( 0 == exit_code ) { + opts_parse( Options_Config, 1, args ); + // If we fail to call exit then this breaks our test + CHECK( false ); + } else { + CHECK( 1 == exit_code ); } + opts_reset(); } - TEST(Verify_ParseShortOption_Parses_A_Single_Valid_Option_With_Arg_And_No_Space) + TEST(Verify_ParseOptions_Parses_short_option_with_no_argument) { - char* args[] = { (char*)"b5" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); - + char* args[] = { (char*)"-a" }; CHECK_DOES_NOT_EXIT() { - OPTS_ParseShortOption( &ctx ); - - OptionList_T* result = ctx.results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "b" ) ); - CHECK( NULL != result->tail->val ); - CHECK( 0 == strcmp( result->tail->val, "5" ) ); - CHECK( NULL == result->tail->next ); + opts_parse( Options_Config, 1, args ); + CHECK(opts_is_set("a", NULL)); } + opts_reset(); } - TEST(Verify_ParseShortOption_Parses_A_Single_Valid_Option_With_Arg_And_Space) + TEST(Verify_ParseOptions_Parses_short_option_list_with_no_args) { - char* args[] = { (char*)"b", (char*)"5" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 2, args ); - + char* args[] = { (char*)"-ac" }; CHECK_DOES_NOT_EXIT() { - OPTS_ParseShortOption( &ctx ); - - OptionList_T* result = ctx.results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "b" ) ); - CHECK( NULL != result->tail->val ); - CHECK( 0 == strcmp( result->tail->val, "5" ) ); - CHECK( NULL == result->tail->next ); + opts_parse( Options_Config, 1, args ); + CHECK(opts_is_set("a", NULL)); + CHECK(opts_is_set("c", NULL)); } + opts_reset(); } - TEST(Verify_ParseShortOption_Exits_With_Error_When_No_Arg_Received_When_Expected) + TEST(Verify_ParseOptions_Parses_a_short_option_with_an_argument) { - int exit_code = 0; - char* args[] = { (char*)"b" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); - - exit_code = setjmp( Exit_Point ); - if( 0 == exit_code ) - { - OPTS_ParseShortOption( &ctx ); - // If we fail to call exit then this breaks our test - CHECK( false ); - } - else + char* args[] = { (char*)"-bbaz" }; + CHECK_DOES_NOT_EXIT() { - OptionList_T* result = ctx.results->options; - CHECK( 1 == exit_code ); - CHECK( NULL != result ); - CHECK( NULL == result->head ); - CHECK( NULL == result->tail ); + opts_parse( Options_Config, 1, args ); + CHECK(opts_is_set("b", NULL)); + CHECK(0 == strcmp("baz", opts_get_value("b", NULL))); } + opts_reset(); } - TEST(Verify_ParseShortOption_Parses_A_Group_Of_Valid_Options_With_No_Arg) + TEST(Verify_ParseOptions_Parses_a_short_option_with_an_argument_and_a_space) { - char* args[] = { (char*)"aa" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); - + char* args[] = { (char*)"-b", "baz" }; CHECK_DOES_NOT_EXIT() { - OPTS_ParseShortOption( &ctx ); - - OptionList_T* result = ctx.results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head != result->tail ); - // First option - CHECK( NULL != result->head->key ); - CHECK( 0 == strcmp( result->head->key, "a" ) ); - CHECK( NULL == result->head->val ); - CHECK( NULL != result->head->next ); - // Second option - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "a" ) ); - CHECK( NULL == result->tail->val ); - CHECK( NULL == result->tail->next ); + opts_parse( Options_Config, 2, args ); + CHECK(opts_is_set("b", NULL)); + CHECK(0 == strcmp("baz", opts_get_value("b", NULL))); } + opts_reset(); } - TEST(Verify_ParseShortOption_Parses_A_Group_Of_Valid_Options_With_The_Last_Having_An_Arg) + TEST(Verify_ParseOptions_Parses_a_short_option_with_an_argument_and_an_equals) { - char* args[] = { (char*)"ab5" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); - + char* args[] = { (char*)"-b=baz" }; CHECK_DOES_NOT_EXIT() { - OPTS_ParseShortOption( &ctx ); - - OptionList_T* result = ctx.results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head != result->tail ); - // First option - CHECK( NULL != result->head->key ); - CHECK( 0 == strcmp( result->head->key, "b" ) ); - CHECK( NULL != result->head->val ); - CHECK( 0 == strcmp( result->head->val, "5" ) ); - CHECK( NULL != result->head->next ); - // Second option - CHECK( NULL != result->tail->key ); - CHECK( 0 == strcmp( result->tail->key, "a" ) ); - CHECK( NULL == result->tail->val ); - CHECK( NULL == result->tail->next ); + opts_parse( Options_Config, 1, args ); + CHECK(opts_is_set("b", NULL)); + CHECK(0 == strcmp("baz", opts_get_value("b", NULL))); } + opts_reset(); } - //------------------------------------------------------------------------- - // Test ParseLongOption Function - //------------------------------------------------------------------------- - TEST(Verify_ParseLongOption_Errors_And_Exits_On_Invalid_Option) + + TEST(Verify_ParseOptions_Parses_a_short_option_with_a_missing_param) { int exit_code = 0; - char* args[] = { (char*)"baz" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); + char* args[] = { (char*)"-b" }; exit_code = setjmp( Exit_Point ); - if( 0 == exit_code ) - { - OPTS_ParseLongOption( &ctx ); + if( 0 == exit_code ) { + opts_parse( Options_Config, 1, args ); // If we fail to call exit then this breaks our test CHECK( false ); - } - else - { - OptionList_T* result = ctx.results->options; + } else { CHECK( 1 == exit_code ); - CHECK( NULL != result ); - CHECK( NULL == result->head ); - CHECK( NULL == result->tail ); } + opts_reset(); } - TEST(Verify_ParseLongOption_Errors_And_Exits_Next_Option_Instead_Of_Argument) + TEST(Verify_ParseOptions_Parses_a_short_option_with_a_missing_param) { int exit_code = 0; - char* args[] = { (char*)"bar", (char*)"--foo" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 2, args ); + char* args[] = { (char*)"-b-" }; exit_code = setjmp( Exit_Point ); - if( 0 == exit_code ) - { - OPTS_ParseLongOption( &ctx ); + if( 0 == exit_code ) { + opts_parse( Options_Config, 1, args ); // If we fail to call exit then this breaks our test CHECK( false ); - } - else - { - OptionList_T* result = ctx.results->options; + } else { CHECK( 1 == exit_code ); - CHECK( NULL != result ); - CHECK( NULL == result->head ); - CHECK( NULL == result->tail ); } + opts_reset(); } - TEST(Verify_ParseLongOption_Errors_And_Exits_EOF_Instead_Of_Argument) + TEST(Verify_ParseOptions_exits_when_invalid_short_option) { int exit_code = 0; - char* args[] = { (char*)"bar" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); + char* args[] = { (char*)"-d" }; exit_code = setjmp( Exit_Point ); - if( 0 == exit_code ) - { - OPTS_ParseLongOption( &ctx ); + if( 0 == exit_code ) { + opts_parse( Options_Config, 1, args ); // If we fail to call exit then this breaks our test CHECK( false ); - } - else - { - OptionList_T* result = ctx.results->options; + } else { CHECK( 1 == exit_code ); - CHECK( NULL != result ); - CHECK( NULL == result->head ); - CHECK( NULL == result->tail ); - } - } - - TEST(Verify_ParseLongOption_Parses_Option_With_No_Arg) - { - char* args[] = { (char*)"foo" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); - - CHECK_DOES_NOT_EXIT() - { - OPTS_ParseLongOption( &ctx ); - - OptionList_T* result = ctx.results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( 0 == strcmp( result->head->key, (char*)"foo") ); - CHECK( NULL == result->tail->val ); - } - } - - TEST(Verify_ParseLongOption_Parses_Option_With_Arg_Using_Equals_Sign) - { - char* args[] = { (char*)"bar=baz" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); - - CHECK_DOES_NOT_EXIT() - { - OPTS_ParseLongOption( &ctx ); - - OptionList_T* result = ctx.results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( 0 == strcmp( result->head->key, (char*)"bar") ); - CHECK( 0 == strcmp( result->head->val, (char*)"baz") ); } + opts_reset(); } - TEST(Verify_ParseLongOption_Parses_Option_With_Arg_Not_Using_Equals_Sign) + TEST(Verify_ParseOptions_Parses_A_Floating_Argument) { - char* args[] = { (char*)"bar", (char*)"baz" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 2, args ); + char* args[] = { (char*)"baz1" }; CHECK_DOES_NOT_EXIT() { - OPTS_ParseLongOption( &ctx ); - - OptionList_T* result = ctx.results->options; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( 0 == strcmp( result->head->key, (char*)"bar") ); - CHECK( 0 == strcmp( result->head->val, (char*)"baz") ); + opts_parse( Options_Config, 1, args ); } - } - - //------------------------------------------------------------------------- - // Test ParseArgument Function - //------------------------------------------------------------------------- - TEST(Verify_ParseArgument_Does_Nothing_If_No_Tokens_Left) - { - char* args[] = { (char*)"" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); - - OPTS_ParseArgument( &ctx ); - - ArgumentList_T* result = ctx.results->arguments; - CHECK( NULL != result ); - CHECK( NULL == result->head ); - CHECK( NULL == result->tail ); - } - - TEST(Verify_ParseArgument_Adds_Argument_To_Empty_List) - { - char* args[] = { (char*)"baz1" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); - - OPTS_ParseArgument( &ctx ); - - ArgumentList_T* result = ctx.results->arguments; - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head == result->tail ); - CHECK( 0 == strcmp( result->tail->val, (char*)"baz1" ) ); - CHECK( NULL == result->tail->next ); - } - - TEST(Verify_ParseArgument_Appends_Argument_To_End_Of_List) - { - char* args[] = { (char*)"baz1" }; - StreamContext_T ctx; - ctx.options = Options_Config; - OPTS_InitContext( &ctx, 1, args ); - ArgumentList_T* result = ctx.results->arguments; - Argument_T arg = { 0 }; - result->head = &arg; - result->tail = &arg; - - OPTS_ParseArgument( &ctx ); - - CHECK( NULL != result ); - CHECK( NULL != result->head ); - CHECK( NULL != result->tail ); - CHECK( result->head != result->tail ); - CHECK( 0 == strcmp( result->tail->val, (char*)"baz1" ) ); - CHECK( NULL == result->tail->next ); - } - - //------------------------------------------------------------------------- - // Test GetOptConfig Function - //------------------------------------------------------------------------- - TEST(Verify_GetOptConfig_Can_Retrieve_A_Short_Config_By_Name_And_Type) - { - OptionConfig_T* result = NULL; - result = OPTS_GetOptConfig( Options_Config, SHORT, (char*)"a" ); - CHECK( result == &(Options_Config[0]) ); - } - - TEST(Verify_GetOptConfig_Can_Retrieve_A_Long_Config_By_Name_And_Type) - { - OptionConfig_T* result = NULL; - result = OPTS_GetOptConfig( Options_Config, LONG, (char*)"foo" ); - CHECK( result == &(Options_Config[2]) ); - } - - TEST(Verify_GetOptConfig_Returns_Null_If_No_Config_Found) - { - OptionConfig_T* result = NULL; - result = OPTS_GetOptConfig( Options_Config, LONG, (char*)"baz" ); - CHECK( result == NULL ); - } - - TEST(Verify_GetOptConfig_Returns_Null_If_Config_List_Empty) - { - OptionConfig_T config[] = { - { END, NULL, NULL, 0, NULL } - }; - OptionConfig_T* result = NULL; - result = OPTS_GetOptConfig( config, LONG, (char*)"foo" ); - CHECK( result == NULL ); - } - - //------------------------------------------------------------------------- - // Test AddOption Function - //------------------------------------------------------------------------- - TEST(Verify_AddOption_Ignores_NULL_Result_Set) - { - Result_T results; - results.options = NULL; - - // If we don't segfault here I call it a win - OPTS_AddOption( NULL, NULL, NULL ); - OPTS_AddOption( &results, NULL, NULL ); - } - - TEST(Verify_AddOption_Adds_Result_To_Empty_List) - { - Result_T results; - char name[] = "foo"; - char arg[] = "bar"; - results.options = (OptionList_T*)malloc( sizeof( OptionList_T ) ); - results.options->head = NULL; - results.options->tail = NULL; - OPTS_AddOption( &results, name, arg ); - - CHECK( NULL != results.options->head ); - CHECK( NULL != results.options->tail ); - CHECK( NULL != results.options->head->key ); - CHECK( name != results.options->head->key ); - CHECK( 0 == strcmp( name, results.options->head->key ) ); - CHECK( NULL != results.options->head->val ); - CHECK( arg == results.options->head->val ); - CHECK( NULL == results.options->head->next ); - CHECK( results.options->head == results.options->tail ); - - free(results.options->head->key); - free(results.options->head); - free(results.options); - } - - TEST(Verify_AddOption_Appends_Result_To_Tail_Of_List) - { - Result_T results; - Option_T option = {0}; - char name[] = "foo"; - char arg[] = "bar"; - results.options = (OptionList_T*)malloc( sizeof( OptionList_T ) ); - results.options->head = &option; - results.options->tail = &option; - OPTS_AddOption( &results, name, arg ); - - CHECK( NULL != results.options->head ); - CHECK( NULL != results.options->tail ); - CHECK( results.options->head != results.options->tail ); - CHECK( NULL != results.options->tail->key ); - CHECK( name != results.options->tail->key ); - CHECK( 0 == strcmp( name, results.options->tail->key ) ); - CHECK( NULL != results.options->tail->val ); - CHECK( arg == results.options->tail->val ); - CHECK( NULL == results.options->tail->next ); - - free(results.options->tail->key); - free(results.options->tail); - free(results.options); - } - - //------------------------------------------------------------------------- - // Test ConsumeWhitespaace Function - //------------------------------------------------------------------------- - TEST(Verify_ConsumeWhitespace_Removes_Whitespace_From_The_Stream_Till_The_Next_Token) - { - char* args[] = { (char*)" " }; - StreamContext_T ctx; - ctx.line_idx = 0; - ctx.col_idx = -1; - ctx.arg_count = 1; - ctx.arg_vect = args; - (void)OPTS_NextCharacter( &ctx ); - - OPTS_ConsumeWhitespace( &ctx ); - CHECK( EOF == OPTS_NextCharacter( &ctx ) ); - } - - //------------------------------------------------------------------------- - // Test NextToken Function - //------------------------------------------------------------------------- - TEST(Verify_NextToken_Properly_Tokenizes_Stream) - { - char* token = NULL; - char* args[] = { (char*)"-a", (char*)"b", (char*)"--foo", (char*)"--foo=bar" }; - StreamContext_T ctx; - ctx.line_idx = 0; - ctx.col_idx = -1; - ctx.arg_count = 4; - ctx.arg_vect = args; - - (void)OPTS_NextCharacter( &ctx ); - token = OPTS_NextToken( &ctx ); - CHECK( 0 == strcmp( token, (char*)"-a" ) ); - free( token ); - - (void)OPTS_NextCharacter( &ctx ); - token = OPTS_NextToken( &ctx ); - CHECK( 0 == strcmp( token, (char*)"b" ) ); - free( token ); - - (void)OPTS_NextCharacter( &ctx ); - token = OPTS_NextToken( &ctx ); - CHECK( 0 == strcmp( token, (char*)"--foo" ) ); - free( token ); - - (void)OPTS_NextCharacter( &ctx ); - token = OPTS_NextToken( &ctx ); - CHECK( 0 == strcmp( token, (char*)"--foo" ) ); - free( token ); - - (void)OPTS_NextCharacter( &ctx ); - token = OPTS_NextToken( &ctx ); - CHECK( 0 == strcmp( token, (char*)"bar" ) ); - free( token ); - } - - //------------------------------------------------------------------------- - // Test NextCharacter Function - //------------------------------------------------------------------------- - TEST(Verify_NextCharacter_Can_Loop_Through_Characters) - { - char* args[] = { (char*)"abc", (char*)"123=4" }; - StreamContext_T ctx; - ctx.line_idx = 0; - ctx.col_idx = -1; - ctx.arg_count = 2; - ctx.arg_vect = args; - - CHECK( 'a' == OPTS_NextCharacter( &ctx ) ); - CHECK( 'a' == ctx.current ); - CHECK( 'b' == OPTS_NextCharacter( &ctx ) ); - CHECK( 'b' == ctx.current ); - CHECK( 'c' == OPTS_NextCharacter( &ctx ) ); - CHECK( 'c' == ctx.current ); - CHECK( ' ' == OPTS_NextCharacter( &ctx ) ); - CHECK( ' ' == ctx.current ); - CHECK( '1' == OPTS_NextCharacter( &ctx ) ); - CHECK( '1' == ctx.current ); - CHECK( '2' == OPTS_NextCharacter( &ctx ) ); - CHECK( '2' == ctx.current ); - CHECK( '3' == OPTS_NextCharacter( &ctx ) ); - CHECK( '3' == ctx.current ); - CHECK( ' ' == OPTS_NextCharacter( &ctx ) ); - CHECK( ' ' == ctx.current ); - CHECK( '4' == OPTS_NextCharacter( &ctx ) ); - CHECK( '4' == ctx.current ); - CHECK( ' ' == OPTS_NextCharacter( &ctx ) ); - CHECK( ' ' == ctx.current ); - CHECK( EOF == OPTS_NextCharacter( &ctx ) ); - CHECK( EOF == ctx.current ); - CHECK( EOF == OPTS_NextCharacter( &ctx ) ); - CHECK( EOF == ctx.current ); - } - - TEST(Verify_NextCharacter_Can_Handle_Empty_Input) - { - char* args[] = {}; - StreamContext_T ctx; - ctx.line_idx = 0; - ctx.col_idx = -1; - ctx.arg_count = 0; - ctx.arg_vect = args; - - CHECK( EOF == OPTS_NextCharacter( &ctx ) ); - CHECK( EOF == ctx.current ); - CHECK( EOF == OPTS_NextCharacter( &ctx ) ); - CHECK( EOF == ctx.current ); - } - - //------------------------------------------------------------------------- - // Test AppendCharacter Function - //------------------------------------------------------------------------- - TEST(Verify_AppendCharacter_Dynamically_Resizes_and_Appends_Char) - { - char* str = (char*)malloc(2); - str[0] = 'a'; - str[1] = '\0'; - str = OPTS_AppendCharacter( str, 'b' ); - - CHECK( 0 == strcmp( str, (char*)"ab" ) ); - } + opts_reset(); + } + + + + + + + + + + + + +// TEST(Verify_ParseOptions_exits_when_a_short_option_lacks_the_required_option) +// { +// Result_T* results; +// int exit_code = 0; +// char* args[] = { (char*)"-b-" }; +// +// exit_code = setjmp( Exit_Point ); +// if( 0 == exit_code ) { +// results = opts_parse( Options_Config, 1, args ); +// // If we fail to call exit then this breaks our test +// CHECK( false ); +// } else { +// CHECK( 1 == exit_code ); +// } +// } +// +// TEST(Verify_ParseOptions_exits_when_a_short_option_with_no_accompanying_option) +// { +// Result_T* results; +// int exit_code = 0; +// char* args[] = { (char*)"-b" }; +// +// exit_code = setjmp( Exit_Point ); +// if( 0 == exit_code ) { +// results = opts_parse( Options_Config, 1, args ); +// // If we fail to call exit then this breaks our test +// CHECK( false ); +// } else { +// CHECK( 1 == exit_code ); +// } +// } +// +// TEST(Verify_ParseOptions_errors_on_unknown_option) +// { +// Result_T* results; +// int exit_code = 0; +// char* args[] = { (char*)"-z" }; +// +// exit_code = setjmp( Exit_Point ); +// if( 0 == exit_code ) { +// results = opts_parse( Options_Config, 1, args ); +// // If we fail to call exit then this breaks our test +// CHECK( false ); +// } else { +// CHECK( 1 == exit_code ); +// } +// } +// +// TEST(Verify_ParseOptions_Parses_short_option_group) +// { +// char* args[] = { (char*)"-aa" }; +// +// CHECK_DOES_NOT_EXIT() +// { +// Result_T* results = opts_parse( Options_Config, 1, args ); +// +// OptionList_T* result = results->options; +// CHECK( NULL != result ); +// CHECK( NULL != result->head ); +// CHECK( NULL != result->tail ); +// CHECK( result->head != result->tail ); +// CHECK( NULL != result->head->key ); +// CHECK( 0 == strcmp( result->head->key, "a" ) ); +// CHECK( NULL == result->head->val ); +// CHECK( NULL != result->tail->key ); +// CHECK( 0 == strcmp( result->tail->key, "a" ) ); +// CHECK( NULL == result->tail->val ); +// } +// } +// +// TEST(Verify_ParseOptions_Parses_short_option_group_with_more_than_2_options) +// { +// char* args[] = { (char*)"-aaaa" }; +// +// CHECK_DOES_NOT_EXIT() +// { +// Result_T* results = opts_parse( Options_Config, 1, args ); +// +// OptionList_T* result = results->options; +// CHECK( NULL != result ); +// CHECK( NULL != result->head ); +// CHECK( NULL != result->tail ); +// CHECK( result->head != result->tail ); +// } +// } +// +// TEST(Verify_ParseOptions_Parses_short_option_group_with_the_last_having_an_arg) +// { +// char* args[] = { (char*)"-ab5" }; +// +// CHECK_DOES_NOT_EXIT() +// { +// Result_T* results = opts_parse( Options_Config, 1, args ); +// OptionList_T* result = results->options; +// CHECK( NULL != result ); +// CHECK( NULL != result->head ); +// CHECK( NULL != result->tail ); +// CHECK( result->head != result->tail ); +// CHECK( NULL != result->head->key ); +// CHECK( 0 == strcmp( result->head->key, "b" ) ); +// CHECK( NULL != result->head->val ); +// CHECK( 0 == strcmp( result->head->val, "5" ) ); +// CHECK( NULL != result->tail->key ); +// CHECK( 0 == strcmp( result->tail->key, "a" ) ); +// CHECK( NULL == result->tail->val ); +// } +// } +// +// TEST(Verify_ParseOptions_Parses_A_Short_Option_With_No_Param) +// { +// char* args[] = { (char*)"-a" }; +// +// CHECK_DOES_NOT_EXIT() +// { +// Result_T* results = opts_parse( Options_Config, 1, args ); +// +// OptionList_T* result = results->options; +// CHECK( NULL != result ); +// CHECK( NULL != result->head ); +// CHECK( NULL != result->tail ); +// CHECK( result->head == result->tail ); +// CHECK( NULL != result->tail->key ); +// CHECK( 0 == strcmp( result->tail->key, "a" ) ); +// CHECK( NULL == result->tail->val ); +// CHECK( NULL == result->tail->next ); +// } +// } +// +// TEST(Verify_ParseOptions_Parses_A_Short_Option_With_A_Param_And_A_Space) +// { +// char* args[] = { (char*)"-b", (char*)"5" }; +// +// CHECK_DOES_NOT_EXIT() +// { +// Result_T* results = opts_parse( Options_Config, 2, args ); +// +// OptionList_T* result = results->options; +// CHECK( NULL != result ); +// CHECK( NULL != result->head ); +// CHECK( NULL != result->tail ); +// CHECK( result->head == result->tail ); +// CHECK( NULL != result->tail->key ); +// CHECK( 0 == strcmp( result->tail->key, "b" ) ); +// CHECK( NULL != result->tail->val ); +// CHECK( 0 == strcmp( result->tail->val, "5" ) ); +// CHECK( NULL == result->tail->next ); +// } +// } +// +// TEST(Verify_ParseOptions_Parses_A_Short_Option_With_A_Param_And_No_Space) +// { +// char* args[] = { (char*)"-b5" }; +// +// CHECK_DOES_NOT_EXIT() +// { +// Result_T* results = opts_parse( Options_Config, 1, args ); +// +// OptionList_T* result = results->options; +// CHECK( NULL != result ); +// CHECK( NULL != result->head ); +// CHECK( NULL != result->tail ); +// CHECK( result->head == result->tail ); +// CHECK( NULL != result->tail->key ); +// CHECK( 0 == strcmp( result->tail->key, "b" ) ); +// CHECK( NULL != result->tail->val ); +// CHECK( 0 == strcmp( result->tail->val, "5" ) ); +// CHECK( NULL == result->tail->next ); +// } +// } }