@ -8,7 +8,7 @@ class Argv {
public :
public :
Argv ( std : : initializer_list < const char * > args )
Argv ( std : : initializer_list < const char * > args )
: m_argv ( new char * [ args . size ( ) ] )
: m_argv ( new const char * [ args . size ( ) ] )
, m_argc ( static_cast < int > ( args . size ( ) ) )
, m_argc ( static_cast < int > ( args . size ( ) ) )
{
{
int i = 0 ;
int i = 0 ;
@ -26,7 +26,7 @@ class Argv {
}
}
}
}
char * * argv ( ) const {
const char * * argv ( ) const {
return m_argv . get ( ) ;
return m_argv . get ( ) ;
}
}
@ -36,8 +36,8 @@ class Argv {
private :
private :
std : : vector < std : : unique_ptr < char [ ] > > m_args ;
std : : unique_ptr < char * [ ] > m_argv ;
std : : vector < std : : unique_ptr < char [ ] > > m_args { } ;
std : : unique_ptr < const char * [ ] > m_argv ;
int m_argc ;
int m_argc ;
} ;
} ;
@ -69,7 +69,7 @@ TEST_CASE("Basic options", "[options]")
" --space " ,
" --space " ,
} ) ;
} ) ;
char * * actual_argv = argv . argv ( ) ;
auto * * actual_argv = argv . argv ( ) ;
auto argc = argv . argc ( ) ;
auto argc = argv . argc ( ) ;
auto result = options . parse ( argc , actual_argv ) ;
auto result = options . parse ( argc , actual_argv ) ;
@ -125,7 +125,7 @@ TEST_CASE("No positional", "[positional]")
Argv av ( { " tester " , " a " , " b " , " def " } ) ;
Argv av ( { " tester " , " a " , " b " , " def " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
@ -154,7 +154,7 @@ TEST_CASE("All positional", "[positional]")
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
REQUIRE ( argc = = 1 ) ;
CHECK ( result . unmatched ( ) . size ( ) = = 0 ) ;
REQUIRE ( positional . size ( ) = = 3 ) ;
REQUIRE ( positional . size ( ) = = 3 ) ;
CHECK ( positional [ 0 ] = = " a " ) ;
CHECK ( positional [ 0 ] = = " a " ) ;
@ -177,12 +177,12 @@ TEST_CASE("Some positional explicit", "[positional]")
Argv av ( { " tester " , " --output " , " a " , " b " , " c " , " d " } ) ;
Argv av ( { " tester " , " --output " , " a " , " b " , " c " , " d " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
CHECK ( argc = = 1 ) ;
CHECK ( result . unmatched ( ) . size ( ) = = 0 ) ;
CHECK ( result . count ( " output " ) ) ;
CHECK ( result . count ( " output " ) ) ;
CHECK ( result [ " input " ] . as < std : : string > ( ) = = " b " ) ;
CHECK ( result [ " input " ] . as < std : : string > ( ) = = " b " ) ;
CHECK ( result [ " output " ] . as < std : : string > ( ) = = " a " ) ;
CHECK ( result [ " output " ] . as < std : : string > ( ) = = " a " ) ;
@ -203,17 +203,16 @@ TEST_CASE("No positional with extras", "[positional]")
Argv av ( { " extras " , " -- " , " a " , " b " , " c " , " d " } ) ;
Argv av ( { " extras " , " -- " , " a " , " b " , " c " , " d " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto old_argv = argv ;
auto old_argv = argv ;
auto old_argc = argc ;
auto old_argc = argc ;
options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
REQUIRE ( argc = = old_argc - 1 ) ;
CHECK ( argv [ 0 ] = = std : : string ( " extras " ) ) ;
CHECK ( argv [ 1 ] = = std : : string ( " a " ) ) ;
auto & unmatched = result . unmatched ( ) ;
CHECK ( ( unmatched = = std : : vector < std : : string > { " a " , " b " , " c " , " d " } ) ) ;
}
}
TEST_CASE ( " Positional not valid " , " [positional] " ) {
TEST_CASE ( " Positional not valid " , " [positional] " ) {
@ -226,12 +225,37 @@ TEST_CASE("Positional not valid", "[positional]") {
Argv av ( { " foobar " , " bar " , " baz " } ) ;
Argv av ( { " foobar " , " bar " , " baz " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
CHECK_THROWS_AS ( options . parse ( argc , argv ) , cxxopts : : option_not_exists_exception & ) ;
CHECK_THROWS_AS ( options . parse ( argc , argv ) , cxxopts : : option_not_exists_exception & ) ;
}
}
TEST_CASE ( " Positional with empty arguments " , " [positional] " ) {
cxxopts : : Options options ( " positional_with_empty_arguments " , " positional with empty argument " ) ;
options . add_options ( )
( " long " , " a long option " , cxxopts : : value < std : : string > ( ) )
( " program " , " program to run " , cxxopts : : value < std : : string > ( ) )
( " programArgs " , " program arguments " , cxxopts : : value < std : : vector < std : : string > > ( ) )
;
options . parse_positional ( " program " , " programArgs " ) ;
Argv av ( { " foobar " , " --long " , " long_value " , " -- " , " someProgram " , " ab " , " -c " , " d " , " --ef " , " gh " , " --ijk=lm " , " n " , " " , " o " , } ) ;
std : : vector < std : : string > expected ( { " ab " , " -c " , " d " , " --ef " , " gh " , " --ijk=lm " , " n " , " " , " o " , } ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto actual = result [ " programArgs " ] . as < std : : vector < std : : string > > ( ) ;
REQUIRE ( result . count ( " program " ) = = 1 ) ;
REQUIRE ( result [ " program " ] . as < std : : string > ( ) = = " someProgram " ) ;
REQUIRE ( result . count ( " programArgs " ) = = expected . size ( ) ) ;
REQUIRE ( actual = = expected ) ;
}
TEST_CASE ( " Empty with implicit value " , " [implicit] " )
TEST_CASE ( " Empty with implicit value " , " [implicit] " )
{
{
cxxopts : : Options options ( " empty_implicit " , " doesn't handle empty " ) ;
cxxopts : : Options options ( " empty_implicit " , " doesn't handle empty " ) ;
@ -241,7 +265,7 @@ TEST_CASE("Empty with implicit value", "[implicit]")
Argv av ( { " implicit " , " --implicit= " } ) ;
Argv av ( { " implicit " , " --implicit= " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
@ -260,7 +284,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION ( " When no value provided " ) {
SECTION ( " When no value provided " ) {
Argv av ( { " no_implicit " , " --bool " } ) ;
Argv av ( { " no_implicit " , " --bool " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
CHECK_THROWS_AS ( options . parse ( argc , argv ) , cxxopts : : missing_argument_exception & ) ;
CHECK_THROWS_AS ( options . parse ( argc , argv ) , cxxopts : : missing_argument_exception & ) ;
@ -269,7 +293,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION ( " With equal-separated true " ) {
SECTION ( " With equal-separated true " ) {
Argv av ( { " no_implicit " , " --bool=true " } ) ;
Argv av ( { " no_implicit " , " --bool=true " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
@ -280,7 +304,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION ( " With equal-separated false " ) {
SECTION ( " With equal-separated false " ) {
Argv av ( { " no_implicit " , " --bool=false " } ) ;
Argv av ( { " no_implicit " , " --bool=false " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
@ -291,7 +315,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION ( " With space-separated true " ) {
SECTION ( " With space-separated true " ) {
Argv av ( { " no_implicit " , " --bool " , " true " } ) ;
Argv av ( { " no_implicit " , " --bool " , " true " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
@ -302,7 +326,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION ( " With space-separated false " ) {
SECTION ( " With space-separated false " ) {
Argv av ( { " no_implicit " , " --bool " , " false " } ) ;
Argv av ( { " no_implicit " , " --bool " , " false " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
@ -323,7 +347,7 @@ TEST_CASE("Default values", "[default]")
SECTION ( " Sets defaults " ) {
SECTION ( " Sets defaults " ) {
Argv av ( { " implicit " } ) ;
Argv av ( { " implicit " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
@ -339,7 +363,7 @@ TEST_CASE("Default values", "[default]")
SECTION ( " When values provided " ) {
SECTION ( " When values provided " ) {
Argv av ( { " implicit " , " --default " , " 5 " } ) ;
Argv av ( { " implicit " , " --default " , " 5 " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
@ -374,7 +398,7 @@ TEST_CASE("Integers", "[options]")
Argv av ( { " ints " , " -- " , " 5 " , " 6 " , " -6 " , " 0 " , " 0xab " , " 0xAf " , " 0x0 " } ) ;
Argv av ( { " ints " , " -- " , " 5 " , " 6 " , " -6 " , " 0 " , " 0xab " , " 0xAf " , " 0x0 " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
options . parse_positional ( " positional " ) ;
options . parse_positional ( " positional " ) ;
@ -401,7 +425,7 @@ TEST_CASE("Leading zero integers", "[options]")
Argv av ( { " ints " , " -- " , " 05 " , " 06 " , " 0x0ab " , " 0x0001 " } ) ;
Argv av ( { " ints " , " -- " , " 05 " , " 06 " , " 0x0ab " , " 0x0001 " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
options . parse_positional ( " positional " ) ;
options . parse_positional ( " positional " ) ;
@ -425,7 +449,7 @@ TEST_CASE("Unsigned integers", "[options]")
Argv av ( { " ints " , " -- " , " -2 " } ) ;
Argv av ( { " ints " , " -- " , " -2 " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
options . parse_positional ( " positional " ) ;
options . parse_positional ( " positional " ) ;
@ -504,7 +528,7 @@ TEST_CASE("Floats", "[options]")
Argv av ( { " floats " , " --double " , " 0.5 " , " -- " , " 4 " , " -4 " , " 1.5e6 " , " -1.5e6 " } ) ;
Argv av ( { " floats " , " --double " , " 0.5 " , " -- " , " 4 " , " -4 " , " 1.5e6 " , " -1.5e6 " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
options . parse_positional ( " positional " ) ;
options . parse_positional ( " positional " ) ;
@ -529,7 +553,7 @@ TEST_CASE("Invalid integers", "[integer]") {
Argv av ( { " ints " , " -- " , " Ae " } ) ;
Argv av ( { " ints " , " -- " , " Ae " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
options . parse_positional ( " positional " ) ;
options . parse_positional ( " positional " ) ;
@ -554,7 +578,7 @@ TEST_CASE("Booleans", "[boolean]") {
Argv av ( { " booleans " , " --bool=false " , " --debug=true " , " --timing " , " --verbose=1 " , " --dry-run=0 " , " extra " } ) ;
Argv av ( { " booleans " , " --bool=false " , " --debug=true " , " --timing " , " --verbose=1 " , " --dry-run=0 " , " extra " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
@ -588,7 +612,7 @@ TEST_CASE("std::vector", "[vector]") {
Argv av ( { " vector " , " --vector " , " 1,-2.1,3,4.5 " } ) ;
Argv av ( { " vector " , " --vector " , " 1,-2.1,3,4.5 " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
options . parse ( argc , argv ) ;
options . parse ( argc , argv ) ;
@ -609,7 +633,7 @@ TEST_CASE("std::optional", "[optional]") {
Argv av ( { " optional " , " --optional " , " foo " } ) ;
Argv av ( { " optional " , " --optional " , " foo " } ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
options . parse ( argc , argv ) ;
options . parse ( argc , argv ) ;
@ -632,9 +656,10 @@ TEST_CASE("Unrecognised options", "[options]") {
" --long " ,
" --long " ,
" -su " ,
" -su " ,
" --another_unknown " ,
" --another_unknown " ,
" -a " ,
} ) ;
} ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
SECTION ( " Default behaviour " ) {
SECTION ( " Default behaviour " ) {
@ -643,9 +668,9 @@ TEST_CASE("Unrecognised options", "[options]") {
SECTION ( " After allowing unrecognised options " ) {
SECTION ( " After allowing unrecognised options " ) {
options . allow_unrecognised_options ( ) ;
options . allow_unrecognised_options ( ) ;
CHECK_NOTHROW ( options . parse ( argc , argv ) ) ;
REQUIRE ( argc = = 3 ) ;
CHECK_THAT ( argv [ 1 ] , Catch : : Equals ( " --unknown " ) ) ;
auto result = options . parse ( argc , argv ) ;
auto & unmatched = result . unmatched ( ) ;
CHECK ( ( unmatched = = std : : vector < std : : string > { " --unknown " , " -u " , " --another_ unknown " , " -a " } ) ) ;
}
}
}
}
@ -661,7 +686,7 @@ TEST_CASE("Allow bad short syntax", "[options]") {
" -some_bad_short " ,
" -some_bad_short " ,
} ) ;
} ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
SECTION ( " Default behaviour " ) {
SECTION ( " Default behaviour " ) {
@ -684,7 +709,7 @@ TEST_CASE("Invalid option syntax", "[options]") {
" --a " ,
" --a " ,
} ) ;
} ) ;
char * * argv = av . argv ( ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto argc = av . argc ( ) ;
SECTION ( " Default behaviour " ) {
SECTION ( " Default behaviour " ) {
@ -704,7 +729,7 @@ TEST_CASE("Options empty", "[options]") {
" --unknown "
" --unknown "
} ) ;
} ) ;
auto argc = argv_ . argc ( ) ;
auto argc = argv_ . argc ( ) ;
char * * argv = argv_ . argv ( ) ;
auto * * argv = argv_ . argv ( ) ;
CHECK ( options . groups ( ) . empty ( ) ) ;
CHECK ( options . groups ( ) . empty ( ) ) ;
CHECK_THROWS_AS ( options . parse ( argc , argv ) , cxxopts : : option_not_exists_exception & ) ;
CHECK_THROWS_AS ( options . parse ( argc , argv ) , cxxopts : : option_not_exists_exception & ) ;
@ -733,7 +758,7 @@ TEST_CASE("Initializer list with group", "[options]") {
" 8000 " ,
" 8000 " ,
" -t " ,
" -t " ,
} ) ;
} ) ;
char * * actual_argv = argv . argv ( ) ;
auto * * actual_argv = argv . argv ( ) ;
auto argc = argv . argc ( ) ;
auto argc = argv . argc ( ) ;
auto result = options . parse ( argc , actual_argv ) ;
auto result = options . parse ( argc , actual_argv ) ;
@ -763,7 +788,7 @@ TEST_CASE("Option add with add_option(string, Option)", "[options]") {
" 4 "
" 4 "
} ) ;
} ) ;
auto argc = argv_ . argc ( ) ;
auto argc = argv_ . argc ( ) ;
char * * argv = argv_ . argv ( ) ;
auto * * argv = argv_ . argv ( ) ;
auto result = options . parse ( argc , argv ) ;
auto result = options . parse ( argc , argv ) ;
CHECK ( result . arguments ( ) . size ( ) = = 2 ) ;
CHECK ( result . arguments ( ) . size ( ) = = 2 ) ;
@ -774,3 +799,34 @@ TEST_CASE("Option add with add_option(string, Option)", "[options]") {
CHECK ( result [ " aggregate " ] . as < int > ( ) = = 4 ) ;
CHECK ( result [ " aggregate " ] . as < int > ( ) = = 4 ) ;
CHECK ( result [ " test " ] . as < int > ( ) = = 5 ) ;
CHECK ( result [ " test " ] . as < int > ( ) = = 5 ) ;
}
}
TEST_CASE ( " Const array " , " [const] " ) {
const char * const option_list [ ] = { " empty " , " options " } ;
cxxopts : : Options options ( " Empty options " , " - test constness " ) ;
auto result = options . parse ( 2 , option_list ) ;
}
TEST_CASE ( " Parameter follow option " , " [parameter] " ) {
cxxopts : : Options options ( " param_follow_opt " , " - test parameter follow option without space. " ) ;
options . add_options ( )
( " j,job " , " Job " , cxxopts : : value < std : : vector < unsigned > > ( ) ) ;
Argv av ( { " implicit " ,
" -j " , " 9 " ,
" --job " , " 7 " ,
" --job=10 " ,
" -j5 " ,
} ) ;
auto * * argv = av . argv ( ) ;
auto argc = av . argc ( ) ;
auto result = options . parse ( argc , argv ) ;
REQUIRE ( result . count ( " job " ) = = 4 ) ;
auto job_values = result [ " job " ] . as < std : : vector < unsigned > > ( ) ;
CHECK ( job_values [ 0 ] = = 9 ) ;
CHECK ( job_values [ 1 ] = = 7 ) ;
CHECK ( job_values [ 2 ] = = 10 ) ;
CHECK ( job_values [ 3 ] = = 5 ) ;
}