// $Id$ // ============================================================================ // // = LIBRARY // tests // // = DESCRIPTION // This program tests both the short and long option support in // , and demonstrates how to use it. // // = AUTHOR // Don Hinton // // ============================================================================ #include "ace/OS.h" #include "ace/Get_Opt.h" #include "ace/ARGV.h" #include "ace/SString.h" #include "tests/test_config.h" ACE_RCSID(tests, Get_Opt_Test, "$Id$") /* * This is the heart of the test. It sets up the optstring, instantiates ACE_Get_Opt, * add long options, processes them in a loop, and prints out the results to the log. * * It returns 0 for success and 1 for error so we can keep track of the total error * count. */ static int parse_args (int test_number, int ordering, const ACE_TCHAR *test_args, int skip_argv0 = 1, int report_errors = 1) { ACE_TString test; ACE_TString optstring; // Test the skip_argv0 for the first test only. if (skip_argv0 > 0) { test = ACE_TEXT ("Test_"); ACE_TCHAR s[20]; test += ACE_OS::itoa (test_number, s, 10); test += ACE_TEXT (" "); } test += test_args; optstring += ACE_TEXT ("fr:o::sW;"); ACE_DEBUG ((LM_INFO, " TEST %d ************************************************************\n", test_number)); ACE_DEBUG ((LM_INFO, " Command line: \"%s\"\n", test.c_str ())); ACE_ARGV args (test.c_str ()); ACE_Get_Opt get_opt (args.argc (), args.argv (), optstring.c_str (), skip_argv0, report_errors, ordering); // Now add the default long args. if (get_opt.long_option (ACE_TEXT ("flag"), (int) 'f', ACE_Get_Opt::NO_ARG) != 0) ACE_ERROR_RETURN ((LM_ERROR, " Unable to add long option 'f' \n"), 1); if (get_opt.long_option (ACE_TEXT ("requires_arg"), (int) 'r', ACE_Get_Opt::ARG_REQUIRED) != 0) ACE_ERROR_RETURN ((LM_ERROR, " Unable to add long option 'r' \n"), 1); if (get_opt.long_option (ACE_TEXT ("optional_arg"), (int) 'o', ACE_Get_Opt::ARG_OPTIONAL) != 0) ACE_ERROR_RETURN ((LM_ERROR, " Unable to add long option 'o' \n"), 1); if (get_opt.long_option (ACE_TEXT ("long_option"), (int) 'l', ACE_Get_Opt::ARG_OPTIONAL) != 0) ACE_ERROR_RETURN ((LM_ERROR, " Unable to add long option 'l' \n"), 1); if (get_opt.long_option (ACE_TEXT ("long_only"), ACE_Get_Opt::ARG_REQUIRED) != 0) ACE_ERROR_RETURN ((LM_ERROR, " Unable to add long option \"long_only\" \n"), 1); if (get_opt.long_option (ACE_TEXT ("long_no_arg")) != 0) ACE_ERROR_RETURN ((LM_ERROR, " Unable to add long option \"long_no_arg\" \n"), 1); // This is the special case of providing a non-alpha numeric corresponding // short option. This lets you use the corresponding short option in a // switch statement, even thought a meaningful short options isn't available // (afterall, there are only so many alpha numeric characters available). if (get_opt.long_option (ACE_TEXT ("non_alpha-num_short"), -10, ACE_Get_Opt::ARG_OPTIONAL) != 0) ACE_ERROR_RETURN ((LM_ERROR, " Unable to add long option \"non_alpha_short\" \n"), 1); // We print out the optstring here because adding long_options that // have corresponding short options that aren't yet present, are added. ACE_DEBUG ((LM_INFO, " optstring: \"%s\" skip_argv0: %d\n", get_opt.optstring (), skip_argv0)); // Now, let's parse it... int c = 0; while ((c = get_opt ()) != EOF) { switch (c) { case 0: // Long Option. if (!get_opt.long_option ()) ACE_ERROR_RETURN ((LM_ERROR, " Long option doesn't exist.\n"), 1); ACE_DEBUG ((LM_INFO, " Found long option \"%s\" %s %s\n", get_opt.long_option (), get_opt.opt_arg () ? ACE_TEXT ("with argument:") : ACE_TEXT (""), get_opt.opt_arg () ? get_opt.opt_arg () : ACE_TEXT (""))); break; case 'f': // This flag was added in both the optstring in the ctor and with // long_option(). case 's': // This one is only short and has no long option. ACE_DEBUG ((LM_INFO, " Found option flag '%c'\n", c)); break; case 'r': // This one has a required argument, we wouldn't be here if the // arg were missing. Note that we call get_opt.opt_arg () to return the // argument, but we could have used get_opt.opt_arg () since.opt_arg () // is defined as "opt_arg ()". ACE_DEBUG ((LM_INFO, " Found option '%c' with required argument \"%s\"\n", c, get_opt.opt_arg ())); break; case 'o': // This one has an optional argument. case 'l': // This short options was set automatically added to optstring. ACE_DEBUG ((LM_INFO, " Found option '%c' with optional argument \"%s\"\n", c, get_opt.opt_arg () ? get_opt.opt_arg () : ACE_TEXT ("default"))); break; case 1: // Non-option when in RETURN_IN_ORDER mode. ACE_DEBUG ((LM_INFO, " Found a non-option argument \"%s\" before finding " "\"--\" (must be in RETURN_IN_ORDER mode).\n", get_opt.opt_arg ())); break; case -10: // we found the short option that isn't alpha numeric. ACE_DEBUG ((LM_INFO, " Found option '%d' with optional argument \"%s\"\n", c, get_opt.opt_arg () ? get_opt.opt_arg () : ACE_TEXT ("default"))); break; case ':': // This means an option requiring an argument didn't have one. case '?': // An unrecognized option. default: // This is an error, perhaps you could handle them, but let's // just log it and keep going ACE_DEBUG ((LM_INFO, " Found an unknown option '%c' (%s) we couldn't handle.\n", c, args.argv ()[get_opt.opt_ind () - 1])); } } // Print out the rest of the arguments left in the command line (if any). size_t index = 0; for (index = get_opt.opt_ind (); index < args.argc (); index++) ACE_DEBUG ((LM_INFO, " Found non-option argument \"%s\"\n", args.argv ()[index])); // Now print them all so we can examine the permuted cmd line. for (index = 0; index < args.argc (); index++) ACE_DEBUG ((LM_INFO, " argv[%u] \"%s\"\n", index, args.argv ()[index])); return 0; } /* * Add new tests cases here. We increment the test number and pass the * type of ordering we want so that each test can be tested with multiple * ordering values in order to demostrate the difference. * * The return value is cumulative, and serves as a failure count that is * returned at the end of all the tests. */ static int run_test (int& test_number, int ordering) { int retval = 0; ACE_DEBUG ((LM_INFO, " ########## Running Tests with ordering = %s ##########\n", ordering == 1 ? "REQUIRE_ORDER" : ordering == 2 ? "PERMUTE_ARGS" : "RETURN_IN_ORDER")); // Basic test, but don't use the program name and don't skip any args. retval += parse_args (test_number++, ordering, ACE_TEXT ("-f -rreq-arg -oopt-arg -lopt-arg --long_only=lo_arg -s arg1 arg2"), 0); // Same, but combining short args that don't take args retval += parse_args (test_number++, ordering, ACE_TEXT ("-fsrreq-arg -oopt-arg -lopt-arg --long_only=lo_arg arg1 arg2")); // Now we use defaults for options with optional args. retval += parse_args (test_number++, ordering, ACE_TEXT ("-fsrreq-arg -o -l --long_only=lo_arg arg1 arg2")); // Let's mix up the options and non-options an see what happens. retval += parse_args (test_number++, ordering, ACE_TEXT ("-fs arg1 -rreq-arg -o arg2 -l --long_only=lo_arg")); // Now we turn off options parsing explicitely by passing "--" in the middle. retval += parse_args (test_number++, ordering, ACE_TEXT ("-fs -rreq-arg -- arg1 -o arg2 -l --long_only=lo_arg")); // Let's try the same thing but mix up the options and non-options. retval += parse_args (test_number++, ordering, ACE_TEXT ("-fs arg1 arg2 -rreq-arg -- arg3 -o")); // One more time but with "-W". retval += parse_args (test_number++, ordering, ACE_TEXT ("-fs arg1 arg2 -rreq-arg -W long_option=opt-arg -- arg3 -o")); // Let's pass some long options. retval += parse_args (test_number++, ordering, ACE_TEXT ("--flag -s --requires_arg=req-arg --optional_arg --long_only lo_arg arg1 arg2")); // And long options without the '='. retval += parse_args (test_number++, ordering, ACE_TEXT ("--flag -s --requires_arg req-arg --optional_arg --long_only=lo_arg arg1 arg2")); // Pass "-W" to cause the next argument to be read as a long option. retval += parse_args (test_number++, ordering, ACE_TEXT ("-fso -W requires_arg=req-arg -Woptional_arg -l arg1 arg2")); // This is the special case of a non-alpha numeric short option. retval += parse_args (test_number++, ordering, ACE_TEXT ("-fso --non_alpha-num_short=xxx arg1 arg2")); // Now, let's test some error conditions (we turn off report_errors since they are // intentional, we don't want to break the test script) int report_errors = 0; // Bad short option. retval += parse_args (test_number++, ordering, ACE_TEXT ("-X"), 1, report_errors); // Short option with missing required arg. retval += parse_args (test_number++, ordering, ACE_TEXT ("-r"), 1, report_errors); // Short option with missing required arg with trailing "--". // This reads "--" as the arg, but should it? retval += parse_args (test_number++, ordering, ACE_TEXT ("-r --"), 1, report_errors); // Long option with missing required arg. retval += parse_args (test_number++, ordering, ACE_TEXT ("--long_only"), 1, report_errors); // Long option that doesn't take an arg has one. retval += parse_args (test_number++, ordering, ACE_TEXT ("--long_no_arg=bad_arg"), 1, report_errors); // Unknown long option. retval += parse_args (test_number++, ordering, ACE_TEXT ("--unknown"), 1, report_errors); // Ambigous long option. retval += parse_args (test_number++, ordering, ACE_TEXT ("--long"), 1, report_errors); return retval; } int ACE_TMAIN (int, ACE_TCHAR *argv[]) { ACE_START_TEST (ACE_TEXT ("Get_Opt_Test")); ACE_UNUSED_ARG (argv); int retval = 0; int test_number = 0; // Run the tests for each type of ordering. retval = run_test (test_number, ACE_Get_Opt::PERMUTE_ARGS); retval += run_test (test_number, ACE_Get_Opt::REQUIRE_ORDER); retval += run_test (test_number, ACE_Get_Opt::RETURN_IN_ORDER); ACE_END_TEST; return retval; }