#include <string.h>
#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;
}
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 <stdio.h>
-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;
return str;
}
-
static char* strclone(const char* p_old) {
size_t length = strlen(p_old);
char* p_str = (char*)malloc(length+1);
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;
+}
+
// Unit Test Framework Includes
-#include "test.h"
+#include "atf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 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 }
};
//-----------------------------------------------------------------------------
// 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)
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 );
+// }
+// }
}