MOAB: Mesh Oriented datABase  (version 5.4.1)
test_prog_opt.cpp
Go to the documentation of this file.
00001 #include "TestUtil.hpp"
00002 #include "TestRunner.hpp"
00003 #include "moab/ProgOptions.hpp"
00004 #include <limits>
00005 #include <cstdlib>
00006 #include <iterator>
00007 #ifdef MOAB_HAVE_MPI
00008 #include "moab_mpi.h"
00009 #endif
00010 
00011 void test_flag_opt_short();
00012 void test_flag_opt_long_short();
00013 void test_flag_opt_long();
00014 void test_flag_cancel();
00015 void test_flag_store_false();
00016 
00017 void test_int_opt();
00018 void test_int_arg();
00019 
00020 void test_real_opt();
00021 void test_real_arg();
00022 
00023 void test_string_opt();
00024 void test_string_arg();
00025 void test_string_rank_subst();
00026 
00027 void test_int_vect_opt();
00028 void test_int_vect_arg();
00029 void test_optional_args();
00030 void test_optional_arg();
00031 void test_squashed_short();
00032 
00033 #define ARGCV( A ) ( sizeof( A ) / sizeof( ( A )[0] ) ), const_cast< char** >( A )
00034 
00035 int main( int argc, char* argv[] )
00036 {
00037     // make ProgOptions abort() rather than exiting with an
00038     // error code for invalid options so that we can catch
00039     // the signal and continue with later tests
00040 #ifndef WIN32
00041     setenv( "MOAB_PROG_OPT_ABORT", "1", 0 );
00042 #endif
00043 
00044     REGISTER_TEST( test_flag_opt_short );
00045     REGISTER_TEST( test_flag_opt_long_short );
00046     REGISTER_TEST( test_flag_opt_long );
00047     REGISTER_TEST( test_flag_cancel );
00048     REGISTER_TEST( test_flag_store_false );
00049 
00050     REGISTER_TEST( test_int_opt );
00051     REGISTER_TEST( test_int_arg );
00052     REGISTER_TEST( test_real_opt );
00053     REGISTER_TEST( test_real_arg );
00054 
00055     REGISTER_TEST( test_string_opt );
00056     REGISTER_TEST( test_string_arg );
00057     REGISTER_TEST( test_string_rank_subst );
00058 
00059     REGISTER_TEST( test_int_vect_opt );
00060     REGISTER_TEST( test_int_vect_arg );
00061     REGISTER_TEST( test_optional_args );
00062     REGISTER_TEST( test_optional_arg );
00063     REGISTER_TEST( test_squashed_short );
00064 
00065 #ifdef MOAB_HAVE_MPI
00066     MPI_Init( &argc, &argv );
00067 #endif
00068     int result = RUN_TESTS( argc, argv );
00069 #ifdef MOAB_HAVE_MPI
00070     MPI_Finalize();
00071 #endif
00072     return result;
00073 }
00074 
00075 void test_flag_opt_short()
00076 {
00077     ProgOptions opts1;
00078     bool value1 = false;
00079     opts1.addOpt< void >( ",s", "short opt", &value1 );
00080     const char* argv1[] = { "prog", "-s" };
00081     opts1.parseCommandLine( ARGCV( argv1 ) );
00082     CHECK( value1 );
00083     CHECK_EQUAL( 1, opts1.numOptSet( ",s" ) );
00084 }
00085 
00086 void test_flag_opt_long_short()
00087 {
00088     ProgOptions opts2;
00089     bool value = false;
00090     opts2.addOpt< void >( "long,l", "long opt", &value );
00091     const char* argv2[] = { "prog", "-l", "-l" };
00092     opts2.parseCommandLine( ARGCV( argv2 ) );
00093     CHECK( value );
00094     CHECK_EQUAL( 2, opts2.numOptSet( ",l" ) );
00095     CHECK_EQUAL( 2, opts2.numOptSet( "long,l" ) );
00096     CHECK_EQUAL( 2, opts2.numOptSet( "long" ) );
00097 }
00098 
00099 void test_flag_opt_long()
00100 {
00101     ProgOptions opts3;
00102     bool value = false;
00103     opts3.addOpt< void >( "long,l", "long opt", &value );
00104     const char* argv3[] = { "prog", "--long", "--long" };
00105     opts3.parseCommandLine( ARGCV( argv3 ) );
00106     CHECK( value );
00107     CHECK_EQUAL( 2, opts3.numOptSet( ",l" ) );
00108     CHECK_EQUAL( 2, opts3.numOptSet( "long,l" ) );
00109     CHECK_EQUAL( 2, opts3.numOptSet( "long" ) );
00110 }
00111 
00112 void test_flag_cancel()
00113 {
00114     ProgOptions opts1;
00115     bool value = false;
00116     opts1.addOpt< void >( "flag", "my flag", &value, ProgOptions::add_cancel_opt );
00117     const char* argv1[] = { "test", "--flag" };
00118     opts1.parseCommandLine( ARGCV( argv1 ) );
00119     CHECK( value );
00120 
00121     ProgOptions opts2;
00122     value = true;
00123     opts2.addOpt< void >( "flag", "my flag", &value, ProgOptions::add_cancel_opt );
00124     const char* argv2[] = { "test", "--flag", "--no-flag" };
00125     opts2.parseCommandLine( ARGCV( argv2 ) );
00126     CHECK( !value );
00127 
00128     ProgOptions opts3;
00129     value = false;
00130     opts3.addOpt< void >( "flag", "my flag", &value, ProgOptions::add_cancel_opt );
00131     const char* argv3[] = { "test", "--flag", "--no-flag", "--flag" };
00132     opts3.parseCommandLine( ARGCV( argv3 ) );
00133     CHECK( value );
00134 }
00135 
00136 void test_flag_store_false()
00137 {
00138     ProgOptions opts1;
00139     bool value1 = true;
00140     opts1.addOpt< void >( ",s", "short opt", &value1, ProgOptions::store_false );
00141     const char* argv1[] = { "prog", "-s" };
00142     opts1.parseCommandLine( ARGCV( argv1 ) );
00143     CHECK( !value1 );
00144 }
00145 
00146 void test_int_opt()
00147 {
00148     ProgOptions opts;
00149     int val1 = -1;
00150     opts.addOpt( "long,s", "my int opt", &val1 );
00151     const char* argv[] = { "test", "-s", "2", "--long", "-0xA", "--long=5" };
00152     opts.parseCommandLine( ARGCV( argv ) );
00153     CHECK_EQUAL( 5, val1 );
00154     int val2 = -1;
00155     CHECK( opts.getOpt( ",s", &val2 ) );
00156     CHECK_EQUAL( 5, val2 );
00157     val2 = -1;
00158     CHECK( opts.getOpt( "long,s", &val2 ) );
00159     CHECK_EQUAL( 5, val2 );
00160     val2 = -1;
00161     CHECK( opts.getOpt( "long", &val2 ) );
00162     CHECK_EQUAL( 5, val2 );
00163     std::vector< int > list;
00164     opts.getOptAllArgs( ",s", list );
00165     CHECK_EQUAL( (size_t)3, list.size() );
00166     CHECK_EQUAL( 2, list[0] );
00167     CHECK_EQUAL( -10, list[1] );
00168     CHECK_EQUAL( 5, list[2] );
00169 }
00170 
00171 void test_int_arg()
00172 {
00173     ProgOptions opts;
00174     int val1 = 5;
00175     opts.addRequiredArg( "arg", "my test arg", &val1 );
00176     opts.addRequiredArg< int >( "arg2", "my other test arg" );
00177     const char* argv[] = { "test", "--", "-1", "-010" };
00178     opts.parseCommandLine( ARGCV( argv ) );
00179     CHECK_EQUAL( -1, val1 );
00180     CHECK_EQUAL( -010, opts.getReqArg< int >( "arg2" ) );  // octal -10 == decimal -8
00181     CHECK_EQUAL( -1, opts.getReqArg< int >( "arg" ) );
00182 }
00183 
00184 void test_real_opt()
00185 {
00186     const double EPS = std::numeric_limits< double >::epsilon();
00187     ProgOptions opts;
00188     double val1 = -1;
00189     opts.addOpt( "long,s", "my real opt", &val1 );
00190     const char* argv[] = { "test", "-s", "2", "--long", "2e5", "--long=-0.01" };
00191     opts.parseCommandLine( ARGCV( argv ) );
00192     CHECK_REAL_EQUAL( -0.01, val1, EPS );
00193     double val2 = -1;
00194     CHECK( opts.getOpt( ",s", &val2 ) );
00195     CHECK_REAL_EQUAL( -0.01, val2, EPS );
00196     val2 = -1;
00197     CHECK( opts.getOpt( "long,s", &val2 ) );
00198     CHECK_REAL_EQUAL( -0.01, val2, EPS );
00199     val2 = -1;
00200     CHECK( opts.getOpt( "long", &val2 ) );
00201     CHECK_REAL_EQUAL( -0.01, val2, EPS );
00202     std::vector< double > list;
00203     opts.getOptAllArgs( ",s", list );
00204     CHECK_EQUAL( (size_t)3, list.size() );
00205     CHECK_REAL_EQUAL( 2, list[0], EPS );
00206     CHECK_REAL_EQUAL( 2e5, list[1], EPS );
00207     CHECK_REAL_EQUAL( -0.01, list[2], EPS );
00208 }
00209 
00210 void test_real_arg()
00211 {
00212     const double EPS = std::numeric_limits< double >::epsilon();
00213     ProgOptions opts;
00214     double val1 = 5;
00215     opts.addRequiredArg( "arg", "my test arg", &val1 );
00216     opts.addRequiredArg< double >( "arg2", "my other test arg" );
00217     const char* argv[] = { "test", "--", "-1.2", "1.01e-3" };
00218     opts.parseCommandLine( ARGCV( argv ) );
00219     CHECK_REAL_EQUAL( -1.2, val1, EPS );
00220     CHECK_REAL_EQUAL( 1.01e-3, opts.getReqArg< double >( "arg2" ), EPS );
00221     CHECK_REAL_EQUAL( -1.2, opts.getReqArg< double >( "arg" ), EPS );
00222 }
00223 
00224 void test_string_opt()
00225 {
00226     ProgOptions opts;
00227     std::string val1;
00228     opts.addOpt( "long,s", "my first opt", &val1 );
00229     opts.addOpt< std::string >( "second,2", "my second opt" );
00230 
00231     const char* argv[] = { "test", "--long", "2", "-s", "foobar", "-2", "two", "--second=testval" };
00232     opts.parseCommandLine( ARGCV( argv ) );
00233 
00234     CHECK_EQUAL( "foobar", val1 );
00235     std::string val2;
00236     CHECK( opts.getOpt( ",s", &val2 ) );
00237     CHECK_EQUAL( "foobar", val2 );
00238     val2.clear();
00239     CHECK( opts.getOpt( "long,s", &val2 ) );
00240     CHECK_EQUAL( "foobar", val2 );
00241     val2.clear();
00242     CHECK( opts.getOpt( "long", &val2 ) );
00243     CHECK_EQUAL( "foobar", val2 );
00244 
00245     val2.clear();
00246     CHECK( opts.getOpt( ",2", &val2 ) );
00247     CHECK_EQUAL( "testval", val2 );
00248     val2.clear();
00249     CHECK( opts.getOpt( "second,2", &val2 ) );
00250     CHECK_EQUAL( "testval", val2 );
00251     val2.clear();
00252     CHECK( opts.getOpt( "second", &val2 ) );
00253     CHECK_EQUAL( "testval", val2 );
00254 
00255     std::vector< std::string > list;
00256     opts.getOptAllArgs( "long", list );
00257     CHECK_EQUAL( (size_t)2, list.size() );
00258     CHECK_EQUAL( "2", list[0] );
00259     CHECK_EQUAL( "foobar", list[1] );
00260 
00261     list.clear();
00262     opts.getOptAllArgs( ",2", list );
00263     CHECK_EQUAL( (size_t)2, list.size() );
00264     CHECK_EQUAL( "two", list[0] );
00265     CHECK_EQUAL( "testval", list[1] );
00266 }
00267 
00268 void test_string_arg()
00269 {
00270     ProgOptions opts;
00271     std::string val2;
00272     opts.addRequiredArg< std::string >( "arg", "my test arg" );
00273     opts.addRequiredArg( "arg2", "my other test arg", &val2 );
00274     const char* argv[] = { "test", "my_string", "with spaces" };
00275     opts.parseCommandLine( ARGCV( argv ) );
00276     CHECK_EQUAL( "with spaces", val2 );
00277     CHECK_EQUAL( "my_string", opts.getReqArg< std::string >( "arg" ) );
00278     CHECK_EQUAL( "with spaces", opts.getReqArg< std::string >( "arg2" ) );
00279 }
00280 
00281 void test_string_rank_subst()
00282 {
00283     std::string exp1  = "ddd%";
00284     std::string exp2  = "%";
00285     std::string exp2b = "foo%bar";
00286     std::string exp3  = "%string%";
00287     std::string exp4  = "file.%";
00288 
00289     ProgOptions opts;
00290     std::string val1, val2, val3, val4;
00291     opts.addOpt( ",n", "no subst flag", &val1, 0 );
00292     opts.addOpt( "dosub,s", "subst flag", &val2, ProgOptions::rank_subst );
00293     opts.addRequiredArg( "nos", "no subst arg", &val3, 0 );
00294     opts.addRequiredArg( "sub", "subst arg", &val4, ProgOptions::rank_subst );
00295     std::string eqflg( "--dosub=" );
00296     eqflg += exp2;
00297     const char* argv[] = { "test", exp3.c_str(), exp4.c_str(), "-s", exp2b.c_str(), "-n", exp1.c_str(), eqflg.c_str() };
00298     opts.parseCommandLine( ARGCV( argv ) );
00299 
00300 #ifdef MOAB_HAVE_MPI
00301     int rank, size;
00302     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
00303     MPI_Comm_size( MPI_COMM_WORLD, &size );
00304     char buffer[64];
00305     int width = 1;
00306     while( size > 10 )
00307     {
00308         width++;
00309         size /= 10;
00310     }
00311     sprintf( buffer, "%0*d", width, rank );
00312     exp2  = buffer;
00313     exp2b = std::string( "foo" ) + buffer + "bar";
00314     exp4  = std::string( "file." ) + buffer;
00315 #endif
00316 
00317     CHECK_EQUAL( exp1, val1 );
00318     CHECK_EQUAL( exp2, val2 );
00319     CHECK_EQUAL( exp3, val3 );
00320     CHECK_EQUAL( exp4, val4 );
00321 
00322     val1.clear();
00323     val2.clear();
00324     CHECK( opts.getOpt( ",n", &val1 ) );
00325     CHECK( opts.getOpt( "dosub", &val2 ) );
00326 
00327     CHECK_EQUAL( exp1, val1 );
00328     CHECK_EQUAL( exp2, val2 );
00329     CHECK_EQUAL( exp3, opts.getReqArg< std::string >( "nos" ) );
00330     CHECK_EQUAL( exp4, opts.getReqArg< std::string >( "sub" ) );
00331 
00332     std::vector< std::string > list;
00333     opts.getOptAllArgs( ",s", list );
00334     CHECK_EQUAL( (size_t)2, list.size() );
00335     CHECK_EQUAL( exp2b, list[0] );
00336     CHECK_EQUAL( exp2, list[1] );
00337 }
00338 
00339 void test_int_vect_opt()
00340 {
00341     ProgOptions opts;
00342     std::vector< int > list1, list2;
00343     opts.addOpt( "ids,d", "id list", &list1 );
00344     const char* argv[] = { "test", "--ids=1,2,3", "--ids", "4-10", "-d", "4-5,2" };
00345 
00346     const int exp1[]   = { 1, 2, 3 };
00347     const int exp1_len = sizeof( exp1 ) / sizeof( exp1[0] );
00348     const int exp2[]   = { 4, 5, 6, 7, 8, 9, 10 };
00349     const int exp2_len = sizeof( exp2 ) / sizeof( exp2[0] );
00350     const int exp3[]   = { 4, 5, 2 };
00351     const int exp3_len = sizeof( exp3 ) / sizeof( exp3[0] );
00352     std::vector< int > all;
00353     std::copy( exp1, exp1 + exp1_len, std::back_inserter( all ) );
00354     std::copy( exp2, exp2 + exp2_len, std::back_inserter( all ) );
00355     std::copy( exp3, exp3 + exp3_len, std::back_inserter( all ) );
00356 
00357     opts.parseCommandLine( ARGCV( argv ) );
00358     CHECK_EQUAL( all, list1 );
00359     CHECK( opts.getOpt( ",d", &list2 ) );
00360     CHECK_ARRAYS_EQUAL( exp3, exp3_len, &list2[0], list2.size() );
00361 
00362     std::vector< std::vector< int > > lists;
00363     opts.getOptAllArgs( "ids", lists );
00364     CHECK_EQUAL( (size_t)3, lists.size() );
00365     CHECK_ARRAYS_EQUAL( exp1, exp1_len, &lists[0][0], lists[0].size() );
00366     CHECK_ARRAYS_EQUAL( exp2, exp2_len, &lists[1][0], lists[1].size() );
00367     CHECK_ARRAYS_EQUAL( exp3, exp3_len, &lists[2][0], lists[2].size() );
00368 
00369     list2.clear();
00370     opts.getOptAllArgs( "ids", list2 );
00371     CHECK_EQUAL( all, list2 );
00372 }
00373 
00374 void test_int_vect_arg()
00375 {
00376     ProgOptions opts;
00377     std::vector< int > list1;
00378     opts.addRequiredArg( "ints", "int list", &list1 );
00379     const char* argv[] = { "test", "5,6,-3--1,10" };
00380 
00381     const int exp1[]   = { 5, 6, -3, -2, -1, 10 };
00382     const int exp1_len = sizeof( exp1 ) / sizeof( exp1[0] );
00383 
00384     opts.parseCommandLine( ARGCV( argv ) );
00385     CHECK_ARRAYS_EQUAL( exp1, exp1_len, &list1[0], list1.size() );
00386     CHECK_EQUAL( list1, opts.getReqArg< std::vector< int > >( "ints" ) );
00387 }
00388 
00389 void test_optional_args()
00390 {
00391     ProgOptions opts1;
00392     std::string arg;
00393     opts1.addOptionalArgs< std::string >( 0, "opts", "optional arguments" );
00394     opts1.addRequiredArg( "req", "required final argument", &arg );
00395     const char* argv1[] = { "test", "arg" };
00396     opts1.parseCommandLine( ARGCV( argv1 ) );
00397     std::vector< std::string > list;
00398     CHECK_EQUAL( "arg", arg );
00399     opts1.getArgs( "opts", list );
00400     CHECK( list.empty() );
00401 
00402     ProgOptions opts2;
00403     arg.clear();
00404     opts2.addOptionalArgs< std::string >( 0, "opts", "optional arguments" );
00405     opts2.addRequiredArg( "req", "required final argument", &arg );
00406     const char* argv2[] = { "test", "arg1", "arg2", "arg" };
00407     opts2.parseCommandLine( ARGCV( argv2 ) );
00408     CHECK_EQUAL( "arg", arg );
00409     list.clear();
00410     opts2.getArgs( "opts", list );
00411     CHECK_EQUAL( (size_t)2, list.size() );
00412     CHECK_EQUAL( "arg1", list[0] );
00413     CHECK_EQUAL( "arg2", list[1] );
00414 }
00415 
00416 void test_optional_arg()
00417 {
00418     ProgOptions opts1;
00419     std::string init, fini;
00420     opts1.addRequiredArg( "init", "required initial argument", &init );
00421     opts1.addOptionalArgs< std::string >( 1, "mid", "optional arguments" );
00422     opts1.addRequiredArg( "fini", "required final argument", &fini );
00423     const char* argv1[] = { "test", "arg1", "arg2" };
00424     opts1.parseCommandLine( ARGCV( argv1 ) );
00425     std::vector< std::string > list;
00426     CHECK_EQUAL( "arg1", init );
00427     CHECK_EQUAL( "arg2", fini );
00428     opts1.getArgs( "mid", list );
00429     CHECK( list.empty() );
00430 
00431     ProgOptions opts2;
00432     init.clear();
00433     fini.clear();
00434     opts2.addRequiredArg( "init", "required initial argument", &init );
00435     opts2.addOptionalArgs< std::string >( 1, "mid", "optional arguments" );
00436     opts2.addRequiredArg( "fini", "required final argument", &fini );
00437     const char* argv2[] = { "test", "arg1", "arg2", "arg3" };
00438     opts2.parseCommandLine( ARGCV( argv2 ) );
00439     CHECK_EQUAL( "arg1", init );
00440     CHECK_EQUAL( "arg3", fini );
00441     list.clear();
00442     opts2.getArgs( "mid", list );
00443     CHECK_EQUAL( (size_t)1, list.size() );
00444     CHECK_EQUAL( "arg2", list[0] );
00445 }
00446 
00447 void test_squashed_short()
00448 {
00449     ProgOptions opts;
00450     int intval     = 0;
00451     double realval = 0;
00452     bool flagval   = false;
00453     std::string strval;
00454     opts.addOpt< void >( ",f", "flag", &flagval );
00455     opts.addOpt( ",i", "int", &intval );
00456     opts.addOpt( ",r", "real", &realval );
00457     opts.addOpt( ",s", "str", &strval );
00458 
00459     const char* argv[] = { "test", "-ifsrff", "-0xBEEF", "string", "-1.0e55" };
00460     opts.parseCommandLine( ARGCV( argv ) );
00461 
00462     CHECK_EQUAL( -0xBEEF, intval );
00463     CHECK_REAL_EQUAL( -1.0e55, realval, 1e-6 );
00464     CHECK_EQUAL( "string", strval );
00465     CHECK( flagval );
00466     CHECK_EQUAL( 3, opts.numOptSet( ",f" ) );
00467     CHECK_EQUAL( 1, opts.numOptSet( ",i" ) );
00468     CHECK_EQUAL( 1, opts.numOptSet( ",r" ) );
00469     CHECK_EQUAL( 1, opts.numOptSet( ",s" ) );
00470 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines