LCOV - code coverage report
Current view: top level - tests - catch_options_files.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 494 517 95.6 %
Date: 2022-05-26 21:41:34 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2006-2022  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/advgetopt
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             : 
      20             : // self
      21             : //
      22             : #include    "catch_main.h"
      23             : 
      24             : 
      25             : // advgetopt lib
      26             : //
      27             : #include    <advgetopt/exception.h>
      28             : 
      29             : 
      30             : // snapdev lib
      31             : //
      32             : #include    <snapdev/safe_setenv.h>
      33             : 
      34             : 
      35             : // C++ lib
      36             : //
      37             : #include    <fstream>
      38             : 
      39             : 
      40             : // last include
      41             : //
      42             : #include    <snapdev/poison.h>
      43             : 
      44             : 
      45             : 
      46             : 
      47           8 : CATCH_TEST_CASE("valid_options_files", "[options][valid][files]")
      48             : {
      49          12 :     CATCH_START_SECTION("Check the default path with a nullptr (not a very good test, though)")
      50           1 :         advgetopt::option const options[] =
      51             :         {
      52             :             advgetopt::define_option(
      53             :                   advgetopt::Name("verbose")
      54             :                 , advgetopt::ShortName('v')
      55             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
      56             :                 , advgetopt::Help("a verbose like option, select it or not.")
      57             :             ),
      58             :             advgetopt::end_options()
      59             :         };
      60             : 
      61           1 :         advgetopt::options_environment options_env;
      62           1 :         options_env.f_project_name = "this-is-the-name-of-a-test-project-which-wont-ever-exist";
      63           1 :         options_env.f_options = options;
      64           1 :         options_env.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
      65           1 :         options_env.f_help_header = "Usage: test valid options from file";
      66             : 
      67           1 :         char const * sub_cargv[] =
      68             :         {
      69             :             "tests/unittests/no_file_to_load",
      70             :             "--verbose",
      71             :             nullptr
      72             :         };
      73           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
      74           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
      75             : 
      76           2 :         advgetopt::getopt opt(options_env, sub_argc, sub_argv);
      77             : 
      78             :         // check that the result is valid
      79             : 
      80             :         // an invalid parameter, MUST NOT EXIST
      81           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
      82           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
      83             : 
      84             :         // the valid parameter
      85           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
      86           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
      87           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
      88             : 
      89             :         // other parameters
      90           1 :         CATCH_REQUIRE(opt.get_program_name() == "no_file_to_load");
      91           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/no_file_to_load");
      92             :     CATCH_END_SECTION()
      93             : 
      94          12 :     CATCH_START_SECTION("Check the default path with an empty string (not a very good test, though)")
      95           1 :         advgetopt::option const options[] =
      96             :         {
      97             :             advgetopt::define_option(
      98             :                   advgetopt::Name("verbose")
      99             :                 , advgetopt::ShortName('v')
     100             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     101             :                 , advgetopt::Help("a verbose like option, select it or not.")
     102             :             ),
     103             :             advgetopt::end_options()
     104             :         };
     105             : 
     106           1 :         advgetopt::options_environment options_env;
     107           1 :         options_env.f_project_name = "this-is-the-name-of-a-test-project-which-wont-ever-exist";
     108           1 :         options_env.f_options = options;
     109           1 :         options_env.f_options_files_directory = "";
     110           1 :         options_env.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     111           1 :         options_env.f_help_header = "Usage: test valid options from file";
     112             : 
     113           1 :         char const * sub_cargv[] =
     114             :         {
     115             :             "tests/unittests/no_file_to_load",
     116             :             "--verbose",
     117             :             nullptr
     118             :         };
     119           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     120           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     121             : 
     122           2 :         advgetopt::getopt opt(options_env, sub_argc, sub_argv);
     123             : 
     124             :         // check that the result is valid
     125             : 
     126             :         // an invalid parameter, MUST NOT EXIST
     127           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     128           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     129             : 
     130             :         // the valid parameter
     131           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     132           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     133           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     134             : 
     135             :         // other parameters
     136           1 :         CATCH_REQUIRE(opt.get_program_name() == "no_file_to_load");
     137           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/no_file_to_load");
     138             :     CATCH_END_SECTION()
     139             : 
     140          12 :     CATCH_START_SECTION("Check the parsing of a valid options.ini file")
     141             :         // create a file and make sure it's not read if the project name
     142             :         // is empty
     143             :         //
     144           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     145           1 :         tmpdir += "/shared/advgetopt";
     146           2 :         std::stringstream ss;
     147           1 :         ss << "mkdir -p " << tmpdir;
     148           1 :         if(system(ss.str().c_str()) != 0)
     149             :         {
     150           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     151           0 :             exit(1);
     152             :         }
     153           2 :         std::string const options_filename(tmpdir + "/no-project-name.ini");
     154             : 
     155           1 :         advgetopt::option const valid_options_from_file_list[] =
     156             :         {
     157             :             advgetopt::define_option(
     158             :                   advgetopt::Name("verbose")
     159             :                 , advgetopt::ShortName('v')
     160             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     161             :                 , advgetopt::Help("a verbose like option, select it or not.")
     162             :             ),
     163             :             advgetopt::end_options()
     164             :         };
     165             : 
     166           1 :         advgetopt::options_environment valid_options_from_file;
     167           1 :         valid_options_from_file.f_project_name = nullptr;
     168           1 :         valid_options_from_file.f_options = valid_options_from_file_list;
     169           1 :         valid_options_from_file.f_options_files_directory = tmpdir.c_str();
     170           1 :         valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     171           1 :         valid_options_from_file.f_help_header = "Usage: test valid options from file";
     172             : 
     173             :         {
     174           2 :             std::ofstream options_file;
     175           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     176           1 :             CATCH_REQUIRE(options_file.good());
     177           1 :             options_file <<
     178             :                 "# Auto-generated\n"
     179             : 
     180             :                 "[no-project-name]\n"
     181             :                 "shortname=n\n"
     182             :                 "default='inexistent'\n"
     183             :                 "help=Testing that this doesn't get loaded\n"
     184             :                 "allowed=command-line,environment-variable,configuration-file\n"
     185             :             ;
     186             :         }
     187             : 
     188           1 :         char const * sub_cargv[] =
     189             :         {
     190             :             "tests/unittests/file_not_loaded",
     191             :             "--verbose",
     192             :             nullptr
     193             :         };
     194           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     195           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     196             : 
     197           2 :         advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
     198             : 
     199             :         // check that the result is valid
     200             : 
     201             :         // an invalid parameter, MUST NOT EXIST
     202           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     203           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     204             : 
     205             :         // the valid parameter
     206           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     207           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     208           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     209             : 
     210             :         // "--no-project-name"
     211           1 :         CATCH_REQUIRE(opt.get_option("no-project-name") == nullptr);
     212           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("no-project-name"));
     213             : 
     214             :         // other parameters
     215           1 :         CATCH_REQUIRE(opt.get_program_name() == "file_not_loaded");
     216           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/file_not_loaded");
     217             :     CATCH_END_SECTION()
     218             : 
     219          12 :     CATCH_START_SECTION("Project name is an empty string")
     220             :         // create a file and make sure it's not read if the project name
     221             :         // is empty
     222             :         //
     223           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     224           1 :         tmpdir += "/shared/advgetopt";
     225           2 :         std::stringstream ss;
     226           1 :         ss << "mkdir -p " << tmpdir;
     227           1 :         if(system(ss.str().c_str()) != 0)
     228             :         {
     229           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     230           0 :             exit(1);
     231             :         }
     232           2 :         std::string const options_filename(tmpdir + "/empty-string.ini");
     233             : 
     234           1 :         advgetopt::option const valid_options_from_file_list[] =
     235             :         {
     236             :             advgetopt::define_option(
     237             :                   advgetopt::Name("verbose")
     238             :                 , advgetopt::ShortName('v')
     239             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     240             :                 , advgetopt::Help("a verbose like option, select it or not.")
     241             :             ),
     242             :             advgetopt::end_options()
     243             :         };
     244             : 
     245           1 :         advgetopt::options_environment valid_options_from_file;
     246           1 :         valid_options_from_file.f_project_name = "";
     247           1 :         valid_options_from_file.f_options = valid_options_from_file_list;
     248           1 :         valid_options_from_file.f_options_files_directory = tmpdir.c_str();
     249           1 :         valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     250           1 :         valid_options_from_file.f_help_header = "Usage: test valid options from file";
     251             : 
     252             :         {
     253           2 :             std::ofstream options_file;
     254           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     255           1 :             CATCH_REQUIRE(options_file.good());
     256           1 :             options_file <<
     257             :                 "# Auto-generated\n"
     258             : 
     259             :                 "[no-project-name]\n"
     260             :                 "shortname=n\n"
     261             :                 "default='inexistent'\n"
     262             :                 "help=Testing that this doesn't get loaded\n"
     263             :                 "allowed=command-line,environment-variable,configuration-file\n"
     264             :             ;
     265             :         }
     266             : 
     267           1 :         char const * sub_cargv[] =
     268             :         {
     269             :             "tests/unittests/file_not_loaded",
     270             :             "--verbose",
     271             :             nullptr
     272             :         };
     273           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     274           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     275             : 
     276           2 :         advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
     277             : 
     278             :         // check that the result is valid
     279             : 
     280             :         // an invalid parameter, MUST NOT EXIST
     281           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     282           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     283             : 
     284             :         // the valid parameter
     285           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     286           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     287           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     288             : 
     289             :         // "--no-project-name"
     290           1 :         CATCH_REQUIRE(opt.get_option("no-project-name") == nullptr);
     291           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("no-project-name"));
     292             : 
     293             :         // other parameters
     294           1 :         CATCH_REQUIRE(opt.get_program_name() == "file_not_loaded");
     295           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/file_not_loaded");
     296             :     CATCH_END_SECTION()
     297             : 
     298          12 :     CATCH_START_SECTION("Check the parsing of a valid options.ini file")
     299           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     300           1 :         tmpdir += "/shared/advgetopt";
     301           2 :         std::stringstream ss;
     302           1 :         ss << "mkdir -p " << tmpdir;
     303           1 :         if(system(ss.str().c_str()) != 0)
     304             :         {
     305           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     306           0 :             exit(1);
     307             :         }
     308           2 :         std::string const options_filename(tmpdir + "/unittest.ini");
     309             : 
     310           1 :         advgetopt::option const valid_options_from_file_list[] =
     311             :         {
     312             :             advgetopt::define_option(
     313             :                   advgetopt::Name("verbose")
     314             :                 , advgetopt::ShortName('v')
     315             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     316             :                 , advgetopt::Help("a verbose like option, select it or not.")
     317             :             ),
     318             :             advgetopt::end_options()
     319             :         };
     320             : 
     321           1 :         advgetopt::options_environment valid_options_from_file;
     322           1 :         valid_options_from_file.f_project_name = "unittest";
     323           1 :         valid_options_from_file.f_options = valid_options_from_file_list;
     324           1 :         valid_options_from_file.f_options_files_directory = tmpdir.c_str();
     325           1 :         valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     326           1 :         valid_options_from_file.f_help_header = "Usage: test valid options from file";
     327             : 
     328           1 :         snapdev::safe_setenv env("ADVGETOPT_TEST_OPTIONS"
     329             :                             , "--verbose"
     330             :                              " --more purple"
     331             :                              " -f left.txt center.txt right.txt"
     332             :                              " --size 519"
     333             :                              " --from"
     334           2 :                              " --output destination.txt");
     335             : 
     336             :         {
     337           2 :             std::ofstream options_file;
     338           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     339           1 :             CATCH_REQUIRE(options_file.good());
     340           1 :             options_file <<
     341             :                 "# Auto-generated\n"
     342             : 
     343             :                 "[more]\n"
     344             :                 "shortname=m\n"
     345             :                 "default='More Stuff'\n"
     346             :                 "help=Allow for more stuff to be added\n"
     347             :                 "validator=regex(\"purple|yellow|blue|red|green|orange|brown\")\n"
     348             :                 "allowed=command-line,environment-variable,configuration-file\n"
     349             :                 "show-usage-on-error\n"
     350             :                 "required\n"
     351             : 
     352             :                 "[size]\n"
     353             :                 "shortname=s\n"
     354             :                 "help=Specify the size\n"
     355             :                 "validator=/[0-9]+/\n"
     356             :                 "allowed=environment-variable,configuration-file\n"
     357             :                 "default=31\n"
     358             :                 "required\n"
     359             : 
     360             :                 "[files]\n"
     361             :                 "shortname=f\n"
     362             :                 "help=List of file names\n"
     363             :                 "validator=/.*\\.txt/i\n"
     364             :                 "allowed=command-line,environment-variable\n"
     365             :                 "multiple\n"
     366             :                 "required\n"
     367             : 
     368             :                 "[from]\n"
     369             :                 "shortname=F\n"
     370             :                 "help=Request for the geographcal location representing the origin of the files; optionally you can specify the format\n"
     371             :                 "validator=integer\n"
     372             :                 "allowed=command-line,environment-variable,configuration-file\n"
     373             : 
     374             :                 "[output]\n"
     375             :                 "shortname=o\n"
     376             :                 "default=a.out\n"
     377             :                 "help=output file\n"
     378             :                 "allowed=environment-variable\n"
     379             :                 "required\n"
     380             : 
     381             :                 "[license]\n"
     382             :                 "shortname=l\n"
     383             :                 "help=show this test license\n"
     384             :                 "allowed=command-line\n"
     385             :                 "no-arguments\n"
     386             : 
     387             :                 "[licence]\n"
     388             :                 "alias=license\n"
     389             :                 "allowed=command-line\n"
     390             :                 "no-arguments\n"
     391             :             ;
     392             :         }
     393             : 
     394           1 :         char const * sub_cargv[] =
     395             :         {
     396             :             "tests/unittests/valid_options_files",
     397             :             "--verbose",
     398             :             "--licence",
     399             :             nullptr
     400             :         };
     401           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     402           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     403             : 
     404           2 :         advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
     405             : 
     406             :         // check that the result is valid
     407             : 
     408             :         // an invalid parameter, MUST NOT EXIST
     409           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     410           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     411             : 
     412             :         // the valid parameter
     413           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     414           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     415           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     416             : 
     417             :         // "--more"
     418           1 :         CATCH_REQUIRE(opt.is_defined("more"));
     419           1 :         CATCH_REQUIRE(opt.get_string("more") == "purple");
     420           1 :         CATCH_REQUIRE(opt.get_default("more") == "More Stuff");
     421           1 :         CATCH_REQUIRE(opt.size("more") == 1);
     422             : 
     423             :         // "--size <value>"
     424           1 :         CATCH_REQUIRE(opt.is_defined("size"));
     425           1 :         CATCH_REQUIRE(opt.get_string("size") == "519");
     426           1 :         CATCH_REQUIRE(opt.get_string("size", 0) == "519");
     427           1 :         CATCH_REQUIRE(opt.get_default("size") == "31");
     428           1 :         CATCH_REQUIRE(opt.size("size") == 1);
     429           1 :         CATCH_REQUIRE(opt.get_long("size") == 519);
     430             : 
     431             :         // "--files"
     432           1 :         CATCH_REQUIRE(opt.is_defined("files"));
     433           1 :         CATCH_REQUIRE(opt.get_string("files") == "left.txt");
     434           1 :         CATCH_REQUIRE(opt.get_string("files", 0) == "left.txt");
     435           1 :         CATCH_REQUIRE(opt.get_string("files", 1) == "center.txt");
     436           1 :         CATCH_REQUIRE(opt.get_string("files", 2) == "right.txt");
     437           1 :         CATCH_REQUIRE(opt.get_default("files").empty());
     438           1 :         CATCH_REQUIRE(opt.size("files") == 3);
     439             : 
     440             :         // "--from"
     441           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     442           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     443           1 :         CATCH_REQUIRE(opt.get_string("from") == "");
     444           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     445           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     446           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     447           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     448             : 
     449             :         // "--output"
     450           1 :         CATCH_REQUIRE(opt.is_defined("output"));
     451           1 :         CATCH_REQUIRE(opt.get_string("output") == "destination.txt"); // same as index = 0
     452           1 :         CATCH_REQUIRE(opt.get_string("output",  0) == "destination.txt");
     453           1 :         CATCH_REQUIRE(opt.get_default("output") == "a.out");
     454           1 :         CATCH_REQUIRE(opt.size("output") == 1);
     455             : 
     456             :         // "--from"
     457           1 :         CATCH_REQUIRE(opt.is_defined("license"));
     458           1 :         CATCH_REQUIRE(opt.get_string("license") == "");
     459           1 :         CATCH_REQUIRE(opt.get_default("license").empty());
     460           1 :         CATCH_REQUIRE(opt.size("license") == 1);
     461             : 
     462             :         // other parameters
     463           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     464           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     465             : 
     466           1 :         char const * sub_cargv2[] =
     467             :         {
     468             :             "this/is/ignored",
     469             :             "--from",
     470             :             "1001",
     471             :             nullptr
     472             :         };
     473           1 :         int const sub_argc2(sizeof(sub_cargv2) / sizeof(sub_cargv2[0]) - 1);
     474           1 :         char ** sub_argv2 = const_cast<char **>(sub_cargv2);
     475             : 
     476           1 :         opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     477             : 
     478             :         // "--from"
     479           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     480           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     481           1 :         CATCH_REQUIRE(opt.get_string("from") == "1001");
     482           1 :         CATCH_REQUIRE(opt.get_long("from") == 1001);
     483           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     484             : 
     485             :         // other parameters
     486           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     487           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     488             : 
     489             :         // keep the last value...
     490             :         //
     491           1 :         opt.parse_environment_variable();
     492             : 
     493             :         // "--from"
     494           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     495           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     496           1 :         CATCH_REQUIRE(opt.get_string("from") == "");
     497           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     498           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     499           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     500           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     501             : 
     502             :         // other parameters
     503           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     504           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     505             : 
     506             :         // a reset will restore the state
     507             :         //
     508           1 :         opt.reset();
     509             : 
     510             :         // the valid parameter
     511           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("verbose"));
     512           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     513           1 :         CATCH_REQUIRE(opt.size("verbose") == 0);
     514             : 
     515             :         // "--from"
     516           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("from"));
     517           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     518           1 :         CATCH_REQUIRE(opt.size("from") == 0);
     519             : 
     520           1 :         opt.parse_environment_variable();
     521           1 :         opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     522             : 
     523             :         // "--from"
     524           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     525           1 :         CATCH_REQUIRE(opt.get_string("from") == "1001");
     526           1 :         CATCH_REQUIRE(opt.get_long("from") == 1001);
     527           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     528           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     529             : 
     530             :         // other parameters
     531           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     532           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     533             : 
     534             : 
     535             :         // test that the validators do work here (i.e. generate errors as
     536             :         // expected when we use the wrong options.)
     537             :         //
     538             :         {
     539           1 :             snapdev::safe_setenv subenv("ADVGETOPT_TEST_OPTIONS"
     540             :                                 , "--verbose"
     541             :                                  " --size '1001 meters'"
     542             :                                  " -f valid.cpp"
     543             :                                  " --from auto-build"
     544           2 :                                  " --more black");
     545           1 :             opt.define_environment_variable_data();
     546             : 
     547           1 :             SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"1001 meters\" given to parameter --size is not considered valid.");
     548           1 :             SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"valid.cpp\" given to parameter --files is not considered valid.");
     549           1 :             SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"auto-build\" given to parameter --from is not considered valid.");
     550           1 :             SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"black\" given to parameter --more is not considered valid.");
     551           1 :             opt.parse_environment_variable();
     552           1 :             SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     553             :         }
     554             :     CATCH_END_SECTION()
     555             : 
     556          12 :     CATCH_START_SECTION("Check with validators in the definition")
     557           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     558           1 :         tmpdir += "/shared/advgetopt-validators-in-table";
     559           2 :         std::stringstream ss;
     560           1 :         ss << "mkdir -p " << tmpdir;
     561           1 :         if(system(ss.str().c_str()) != 0)
     562             :         {
     563           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     564           0 :             exit(1);
     565             :         }
     566           2 :         std::string const options_filename(tmpdir + "/unittest.ini");
     567             : 
     568           1 :         advgetopt::option const valid_options_from_file_list[] =
     569             :         {
     570             :             advgetopt::define_option(
     571             :                   advgetopt::Name("verbose")
     572             :                 , advgetopt::ShortName('v')
     573             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     574             :                 , advgetopt::Help("a verbose like option, select it or not.")
     575             :             ),
     576             :             advgetopt::define_option(
     577             :                   advgetopt::Name("size")
     578             :                 , advgetopt::ShortName('s')
     579             :                 , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED>())
     580             :                 , advgetopt::Help("Specify the size.")
     581             :                 , advgetopt::Validator("integer(0...100)")
     582             :                 , advgetopt::DefaultValue("31")
     583             :             ),
     584             :             advgetopt::define_option(
     585             :                   advgetopt::Name("files")
     586             :                 , advgetopt::ShortName('f')
     587             :                 , advgetopt::Help("List of file names")
     588             :                 , advgetopt::Validator("/.*\\.txt/i")
     589             :                 , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED, advgetopt::GETOPT_FLAG_MULTIPLE>())
     590             :             ),
     591             :             advgetopt::define_option(
     592             :                   advgetopt::Name("from")
     593             :                 , advgetopt::ShortName('F')
     594             :                 , advgetopt::Help("Request for the geographcal location representing the origin of the files; optionally you can specify the format")
     595             :                 , advgetopt::Validator("integer")
     596             :                 , advgetopt::Flags(advgetopt::all_flags<>())
     597             :             ),
     598             :             advgetopt::define_option(
     599             :                   advgetopt::Name("more")
     600             :                 , advgetopt::ShortName('m')
     601             :                 , advgetopt::Help("Allow for more stuff to be added")
     602             :                 , advgetopt::Validator("regex(\"purple|yellow|blue|red|green|orange|brown\")")
     603             :                 , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED, advgetopt::GETOPT_FLAG_SHOW_USAGE_ON_ERROR>())
     604             :                 , advgetopt::DefaultValue("More Stuff")
     605             :             ),
     606             :             advgetopt::end_options()
     607             :         };
     608             : 
     609           1 :         advgetopt::options_environment valid_options_from_file;
     610           1 :         valid_options_from_file.f_project_name = "unittest";
     611           1 :         valid_options_from_file.f_options = valid_options_from_file_list;
     612           1 :         valid_options_from_file.f_options_files_directory = tmpdir.c_str();
     613           1 :         valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     614           1 :         valid_options_from_file.f_help_header = "Usage: test valid options from file";
     615             : 
     616           1 :         snapdev::safe_setenv env("ADVGETOPT_TEST_OPTIONS"
     617             :                             , "--verbose"
     618             :                              " --more purple"
     619             :                              " -f left.txt center.txt right.txt"
     620             :                              " --size 19"
     621             :                              " --from"
     622           2 :                              " --output destination.txt");
     623             : 
     624             :         {
     625           2 :             std::ofstream options_file;
     626           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     627           1 :             CATCH_REQUIRE(options_file.good());
     628           1 :             options_file <<
     629             :                 "# Auto-generated\n"
     630             : 
     631             :                 "[output]\n"
     632             :                 "shortname=o\n"
     633             :                 "default=a.out\n"
     634             :                 "help=output file\n"
     635             :                 "allowed=environment-variable\n"
     636             :                 "required\n"
     637             : 
     638             :                 "[license]\n"
     639             :                 "shortname=l\n"
     640             :                 "help=show this test license\n"
     641             :                 "allowed=command-line\n"
     642             :                 "no-arguments\n"
     643             : 
     644             :                 "[licence]\n"
     645             :                 "alias=license\n"
     646             :                 "allowed=command-line\n"
     647             :                 "no-arguments\n"
     648             :             ;
     649             :         }
     650             : 
     651           1 :         char const * sub_cargv[] =
     652             :         {
     653             :             "tests/unittests/valid_options_files",
     654             :             "--verbose",
     655             :             "--licence",
     656             :             nullptr
     657             :         };
     658           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     659           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     660             : 
     661           2 :         advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
     662             : 
     663             :         // check that the result is valid
     664             : 
     665             :         // an invalid parameter, MUST NOT EXIST
     666           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     667           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     668             : 
     669             :         // the valid parameter
     670           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     671           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     672           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     673             : 
     674             :         // "--more"
     675           1 :         CATCH_REQUIRE(opt.is_defined("more"));
     676           1 :         CATCH_REQUIRE(opt.get_string("more") == "purple");
     677           1 :         CATCH_REQUIRE(opt.get_default("more") == "More Stuff");
     678           1 :         CATCH_REQUIRE(opt.size("more") == 1);
     679             : 
     680             :         // "--size <value>"
     681           1 :         CATCH_REQUIRE(opt.is_defined("size"));
     682           1 :         CATCH_REQUIRE(opt.get_string("size") == "19");
     683           1 :         CATCH_REQUIRE(opt.get_string("size", 0) == "19");
     684           1 :         CATCH_REQUIRE(opt.get_default("size") == "31");
     685           1 :         CATCH_REQUIRE(opt.size("size") == 1);
     686           1 :         CATCH_REQUIRE(opt.get_long("size") == 19);
     687             : 
     688             :         // "--files"
     689           1 :         CATCH_REQUIRE(opt.is_defined("files"));
     690           1 :         CATCH_REQUIRE(opt.get_string("files") == "left.txt");
     691           1 :         CATCH_REQUIRE(opt.get_string("files", 0) == "left.txt");
     692           1 :         CATCH_REQUIRE(opt.get_string("files", 1) == "center.txt");
     693           1 :         CATCH_REQUIRE(opt.get_string("files", 2) == "right.txt");
     694           1 :         CATCH_REQUIRE(opt.get_default("files").empty());
     695           1 :         CATCH_REQUIRE(opt.size("files") == 3);
     696             : 
     697             :         // "--from"
     698           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     699           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     700           1 :         CATCH_REQUIRE(opt.get_string("from") == "");
     701           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     702           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     703           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     704           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     705           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     706           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     707           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     708             : 
     709             :         // "--output"
     710           1 :         CATCH_REQUIRE(opt.is_defined("output"));
     711           1 :         CATCH_REQUIRE(opt.get_string("output") == "destination.txt"); // same as index = 0
     712           1 :         CATCH_REQUIRE(opt.get_string("output",  0) == "destination.txt");
     713           1 :         CATCH_REQUIRE(opt.get_default("output") == "a.out");
     714           1 :         CATCH_REQUIRE(opt.size("output") == 1);
     715             : 
     716             :         // "--from"
     717           1 :         CATCH_REQUIRE(opt.is_defined("license"));
     718           1 :         CATCH_REQUIRE(opt.get_string("license") == "");
     719           1 :         CATCH_REQUIRE(opt.get_default("license").empty());
     720           1 :         CATCH_REQUIRE(opt.size("license") == 1);
     721             : 
     722             :         // other parameters
     723           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     724           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     725             : 
     726           1 :         char const * sub_cargv2[] =
     727             :         {
     728             :             "this/is/ignored",
     729             :             "--from",
     730             :             "1001",
     731             :             nullptr
     732             :         };
     733           1 :         int const sub_argc2(sizeof(sub_cargv2) / sizeof(sub_cargv2[0]) - 1);
     734           1 :         char ** sub_argv2 = const_cast<char **>(sub_cargv2);
     735             : 
     736           1 :         opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     737             : 
     738             :         // "--from"
     739           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     740           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     741           1 :         CATCH_REQUIRE(opt.get_string("from") == "1001");
     742           1 :         CATCH_REQUIRE(opt.get_long("from") == 1001);
     743           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     744             : 
     745             :         // other parameters
     746           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     747           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     748             : 
     749             :         // keep the last value...
     750             :         //
     751           1 :         opt.parse_environment_variable();
     752             : 
     753             :         // "--from"
     754           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     755           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     756           1 :         CATCH_REQUIRE(opt.get_string("from") == "");
     757           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     758           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     759           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     760           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     761             : 
     762             :         // other parameters
     763           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     764           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     765             : 
     766             :         // a reset will restore the state
     767             :         //
     768           1 :         opt.reset();
     769             : 
     770             :         // the valid parameter
     771           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("verbose"));
     772           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     773           1 :         CATCH_REQUIRE(opt.size("verbose") == 0);
     774             : 
     775             :         // "--from"
     776           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("from"));
     777           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     778           1 :         CATCH_REQUIRE(opt.size("from") == 0);
     779             : 
     780           1 :         opt.parse_environment_variable();
     781           1 :         opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     782             : 
     783             :         // "--from"
     784           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     785           1 :         CATCH_REQUIRE(opt.get_string("from") == "1001");
     786           1 :         CATCH_REQUIRE(opt.get_long("from") == 1001);
     787           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     788           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     789             : 
     790             :         // other parameters
     791           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     792           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     793             : 
     794             :         // test that the validators do work here (i.e. generate errors as
     795             :         // expected when we use the wrong options.)
     796             :         //
     797           1 :         char const * sub_cargv3[] =
     798             :         {
     799             :             "this/is/ignored",
     800             :             "--size",
     801             :             "1001",
     802             :             "-f",
     803             :             "valid.cpp",
     804             :             "--from",
     805             :             "51",
     806             :             "--more",
     807             :             "black",
     808             :             nullptr
     809             :         };
     810           1 :         int const sub_argc3(sizeof(sub_cargv3) / sizeof(sub_cargv3[0]) - 1);
     811           1 :         char ** sub_argv3 = const_cast<char **>(sub_cargv3);
     812             : 
     813           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"1001\" given to parameter --size is not considered valid.");
     814           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"valid.cpp\" given to parameter --files is not considered valid.");
     815           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"black\" given to parameter --more is not considered valid.");
     816           1 :         opt.parse_arguments(sub_argc3, sub_argv3, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     817           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     818             :     CATCH_END_SECTION()
     819           6 : }
     820             : 
     821             : 
     822           9 : CATCH_TEST_CASE("invalid_options_files", "[options][invalid][files]")
     823             : {
     824          14 :     CATCH_START_SECTION("2+ section names")
     825           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     826           1 :         tmpdir += "/shared/advgetopt";
     827           2 :         std::stringstream ss;
     828           1 :         ss << "mkdir -p " << tmpdir;
     829           1 :         if(system(ss.str().c_str()) != 0)
     830             :         {
     831           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     832           0 :             exit(1);
     833             :         }
     834           2 :         std::string const options_filename(tmpdir + "/bad-section.ini");
     835             : 
     836           1 :         advgetopt::option const options[] =
     837             :         {
     838             :             advgetopt::define_option(
     839             :                   advgetopt::Name("verbose")
     840             :                 , advgetopt::ShortName('v')
     841             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     842             :                 , advgetopt::Help("a verbose like option, select it or not.")
     843             :             ),
     844             :             advgetopt::end_options()
     845             :         };
     846             : 
     847           1 :         advgetopt::options_environment options_environment;
     848           1 :         options_environment.f_project_name = "bad-section";
     849           1 :         options_environment.f_options = options;
     850           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
     851           1 :         options_environment.f_environment_variable_name = nullptr;
     852           1 :         options_environment.f_help_header = "Usage: test invalid section name";
     853             : 
     854             :         {
     855           2 :             std::ofstream options_file;
     856           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     857           1 :             CATCH_REQUIRE(options_file.good());
     858           1 :             options_file <<
     859             :                 "# Auto-generated\n"
     860             : 
     861             :                 "[invalid::name]\n"
     862             :                 "shortname=m\n"
     863             :                 "default='Invalid Stuff'\n"
     864             :                 "help=Testing that a section name can't include \"::\"\n"
     865             :                 "allowed=command-line,environment-variable,configuration-file\n"
     866             :             ;
     867             :         }
     868             : 
     869           1 :         char const * sub_cargv[] =
     870             :         {
     871             :             "tests/unittests/invalid_name_in_options_ini",
     872             :             "--verbose",
     873             :             nullptr
     874             :         };
     875           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     876           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     877             : 
     878           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     879             :                     "error: option name \"shortname\" cannot be added to"
     880             :                     " section \"invalid::name\" because this"
     881             :                     " configuration only accepts one section level.");
     882           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     883             :                     "error: option name \"default\" cannot be added to"
     884             :                     " section \"invalid::name\" because this"
     885             :                     " configuration only accepts one section level.");
     886           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     887             :                     "error: option name \"help\" cannot be added to"
     888             :                     " section \"invalid::name\" because this"
     889             :                     " configuration only accepts one section level.");
     890           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     891             :                     "error: option name \"allowed\" cannot be added to"
     892             :                     " section \"invalid::name\" because this"
     893             :                     " configuration only accepts one section level.");
     894           2 :         advgetopt::getopt::pointer_t opt(std::make_shared<advgetopt::getopt>(options_environment));
     895             :         try
     896             :         {
     897           1 :             opt->finish_parsing(sub_argc, sub_argv);
     898           0 :             CATCH_REQUIRE(false);   // the library is expected to throw here
     899             :         }
     900           2 :         catch(advgetopt::getopt_exit const & e)
     901             :         {
     902           1 :             CATCH_REQUIRE(e.code() == 1);
     903           1 :             CATCH_REQUIRE(e.what() == std::string("getopt_exception: errors were found on your command line, environment variable, or configuration file."));
     904             :         }
     905           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     906             : 
     907           1 :         CATCH_REQUIRE(opt->size("invalid::name::shortname") == 0);
     908           1 :         CATCH_REQUIRE(opt->size("shortname") == 0);
     909             :     CATCH_END_SECTION()
     910             : 
     911          14 :     CATCH_START_SECTION("short name too long")
     912           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     913           1 :         tmpdir += "/shared/advgetopt";
     914           2 :         std::stringstream ss;
     915           1 :         ss << "mkdir -p " << tmpdir;
     916           1 :         if(system(ss.str().c_str()) != 0)
     917             :         {
     918           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     919           0 :             exit(1);
     920             :         }
     921           2 :         std::string const options_filename(tmpdir + "/bad-shortname.ini");
     922             : 
     923           1 :         advgetopt::option const options[] =
     924             :         {
     925             :             advgetopt::define_option(
     926             :                   advgetopt::Name("verbose")
     927             :                 , advgetopt::ShortName('v')
     928             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     929             :                 , advgetopt::Help("a verbose like option, select it or not.")
     930             :             ),
     931             :             advgetopt::end_options()
     932             :         };
     933             : 
     934           1 :         advgetopt::options_environment options_environment;
     935           1 :         options_environment.f_project_name = "bad-shortname";
     936           1 :         options_environment.f_options = options;
     937           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
     938           1 :         options_environment.f_environment_variable_name = nullptr;
     939           1 :         options_environment.f_help_header = "Usage: test invalid shortname";
     940             : 
     941             :         {
     942           2 :             std::ofstream options_file;
     943           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     944           1 :             CATCH_REQUIRE(options_file.good());
     945           1 :             options_file <<
     946             :                 "# Auto-generated\n"
     947             : 
     948             :                 "[badname]\n"
     949             :                 "shortname=to\n"
     950             :                 "default='Invalid Stuff'\n"
     951             :                 "help=Testing that a shotname can't be 2 characters or more\n"
     952             :                 "allowed=command-line,environment-variable,configuration-file\n"
     953             :             ;
     954             :         }
     955             : 
     956           1 :         char const * sub_cargv[] =
     957             :         {
     958             :             "tests/unittests/invalid_name_in_options_ini",
     959             :             "--verbose",
     960             :             nullptr
     961             :         };
     962           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     963           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     964             : 
     965           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
     966             :                     , advgetopt::getopt_logic_error
     967             :                     , Catch::Matchers::ExceptionMessage(
     968             :                               "getopt_logic_error: option \"badname\" has an invalid short name in \""
     969             :                             + options_filename
     970             :                             + "\", it can't be more than one character."));
     971             :     CATCH_END_SECTION()
     972             : 
     973          14 :     CATCH_START_SECTION("missing ')' in validator specification")
     974           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     975           1 :         tmpdir += "/shared/advgetopt";
     976           2 :         std::stringstream ss;
     977           1 :         ss << "mkdir -p " << tmpdir;
     978           1 :         if(system(ss.str().c_str()) != 0)
     979             :         {
     980           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     981           0 :             exit(1);
     982             :         }
     983           2 :         std::string const options_filename(tmpdir + "/bad-validator-parenthesis.ini");
     984             : 
     985           1 :         advgetopt::option const options[] =
     986             :         {
     987             :             advgetopt::define_option(
     988             :                   advgetopt::Name("verbose")
     989             :                 , advgetopt::ShortName('v')
     990             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     991             :                 , advgetopt::Help("a verbose like option, select it or not.")
     992             :             ),
     993             :             advgetopt::end_options()
     994             :         };
     995             : 
     996           1 :         advgetopt::options_environment options_environment;
     997           1 :         options_environment.f_project_name = "bad-validator-parenthesis";
     998           1 :         options_environment.f_options = options;
     999           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1000           1 :         options_environment.f_environment_variable_name = nullptr;
    1001           1 :         options_environment.f_help_header = "Usage: test invalid validator specification";
    1002             : 
    1003             :         {
    1004           2 :             std::ofstream options_file;
    1005           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1006           1 :             CATCH_REQUIRE(options_file.good());
    1007           1 :             options_file <<
    1008             :                 "# Auto-generated\n"
    1009             : 
    1010             :                 "[bad-validator]\n"
    1011             :                 "shortname=b\n"
    1012             :                 "default='Invalid Stuff'\n"
    1013             :                 "help=Testing that a validator with parenthesis must have the ')'\n"
    1014             :                 "validator=regex(\"missing ')'\"\n"
    1015             :                 "allowed=command-line,environment-variable,configuration-file\n"
    1016             :             ;
    1017             :         }
    1018             : 
    1019           1 :         char const * sub_cargv[] =
    1020             :         {
    1021             :             "tests/unittests/invalid_validator_specification",
    1022             :             "--verbose",
    1023             :             nullptr
    1024             :         };
    1025           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1026           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1027             : 
    1028           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1029             :                     , advgetopt::getopt_logic_error
    1030             :                     , Catch::Matchers::ExceptionMessage(
    1031             :                               "getopt_logic_error: invalid validator parameter definition: \"regex(\"missing ')'\"\", the ')' is missing."));
    1032             :     CATCH_END_SECTION()
    1033             : 
    1034          14 :     CATCH_START_SECTION("alias with help")
    1035           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
    1036           1 :         tmpdir += "/shared/advgetopt";
    1037           2 :         std::stringstream ss;
    1038           1 :         ss << "mkdir -p " << tmpdir;
    1039           1 :         if(system(ss.str().c_str()) != 0)
    1040             :         {
    1041           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1042           0 :             exit(1);
    1043             :         }
    1044           2 :         std::string const options_filename(tmpdir + "/alias-with-help.ini");
    1045             : 
    1046           1 :         advgetopt::option const options[] =
    1047             :         {
    1048             :             advgetopt::define_option(
    1049             :                   advgetopt::Name("verbose")
    1050             :                 , advgetopt::ShortName('v')
    1051             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1052             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1053             :             ),
    1054             :             advgetopt::end_options()
    1055             :         };
    1056             : 
    1057           1 :         advgetopt::options_environment options_environment;
    1058           1 :         options_environment.f_project_name = "alias-with-help";
    1059           1 :         options_environment.f_options = options;
    1060           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1061           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1062           1 :         options_environment.f_environment_variable_name = nullptr;
    1063           1 :         options_environment.f_help_header = "Usage: test invalid validator specification";
    1064             : 
    1065             :         {
    1066           2 :             std::ofstream options_file;
    1067           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1068           1 :             CATCH_REQUIRE(options_file.good());
    1069           1 :             options_file <<
    1070             :                 "# Auto-generated\n"
    1071             : 
    1072             :                 "[licence]\n"
    1073             :                 "shortname=l\n"
    1074             :                 "default='Invalid Stuff'\n"
    1075             :                 "alias=license\n"
    1076             :                 "help=Testing that an alias can't accept a help string\n"
    1077             :                 "allowed=command-line,environment-variable,configuration-file\n"
    1078             :             ;
    1079             :         }
    1080             : 
    1081           1 :         char const * sub_cargv[] =
    1082             :         {
    1083             :             "tests/unittests/invalid_alias_specification",
    1084             :             "--verbose",
    1085             :             nullptr
    1086             :         };
    1087           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1088           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1089             : 
    1090           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1091             :                     , advgetopt::getopt_logic_error
    1092             :                     , Catch::Matchers::ExceptionMessage(
    1093             :                               "getopt_logic_error: option \"licence\" is an alias and as such it can't include a help=... parameter in \""
    1094             :                             + options_filename
    1095             :                             + "\"."));
    1096             :     CATCH_END_SECTION()
    1097             : 
    1098          14 :     CATCH_START_SECTION("no-name alias")
    1099           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
    1100           1 :         tmpdir += "/shared/advgetopt";
    1101           2 :         std::stringstream ss;
    1102           1 :         ss << "mkdir -p " << tmpdir;
    1103           1 :         if(system(ss.str().c_str()) != 0)
    1104             :         {
    1105           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1106           0 :             exit(1);
    1107             :         }
    1108           2 :         std::string const options_filename(tmpdir + "/no-name-alias.ini");
    1109             : 
    1110           1 :         advgetopt::option const options[] =
    1111             :         {
    1112             :             advgetopt::define_option(
    1113             :                   advgetopt::Name("verbose")
    1114             :                 , advgetopt::ShortName('v')
    1115             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1116             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1117             :             ),
    1118             :             advgetopt::end_options()
    1119             :         };
    1120             : 
    1121           1 :         advgetopt::options_environment options_environment;
    1122           1 :         options_environment.f_project_name = "no-name-alias";
    1123           1 :         options_environment.f_options = options;
    1124           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1125           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1126           1 :         options_environment.f_environment_variable_name = nullptr;
    1127           1 :         options_environment.f_help_header = "Usage: test alias with no name specified";
    1128             : 
    1129             :         {
    1130           2 :             std::ofstream options_file;
    1131           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1132           1 :             CATCH_REQUIRE(options_file.good());
    1133           1 :             options_file <<
    1134             :                 "# Auto-generated\n"
    1135             : 
    1136             :                 "[foo]\n"
    1137             :                 "shortname=f\n"
    1138             :                 "default='Invalid Stuff'\n"
    1139             :                 "alias=\n"      // name missing (with an equal)
    1140             :                 "allowed=command-line\n"
    1141             :             ;
    1142             :         }
    1143             : 
    1144           1 :         char const * sub_cargv[] =
    1145             :         {
    1146             :             "tests/unittests/non_existant_alias",
    1147             :             "--verbose",
    1148             :             nullptr
    1149             :         };
    1150           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1151           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1152             : 
    1153           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1154             :                     , advgetopt::getopt_logic_error
    1155             :                     , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
    1156             :     CATCH_END_SECTION()
    1157             : 
    1158          14 :     CATCH_START_SECTION("no-name alias v2")
    1159           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
    1160           1 :         tmpdir += "/shared/advgetopt";
    1161           2 :         std::stringstream ss;
    1162           1 :         ss << "mkdir -p " << tmpdir;
    1163           1 :         if(system(ss.str().c_str()) != 0)
    1164             :         {
    1165           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1166           0 :             exit(1);
    1167             :         }
    1168           2 :         std::string const options_filename(tmpdir + "/no-name-alias-v2.ini");
    1169             : 
    1170           1 :         advgetopt::option const options[] =
    1171             :         {
    1172             :             advgetopt::define_option(
    1173             :                   advgetopt::Name("verbose")
    1174             :                 , advgetopt::ShortName('v')
    1175             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1176             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1177             :             ),
    1178             :             advgetopt::end_options()
    1179             :         };
    1180             : 
    1181           1 :         advgetopt::options_environment options_environment;
    1182           1 :         options_environment.f_project_name = "no-name-alias-v2";
    1183           1 :         options_environment.f_options = options;
    1184           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1185           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1186           1 :         options_environment.f_environment_variable_name = nullptr;
    1187           1 :         options_environment.f_help_header = "Usage: test alias with no name specified";
    1188             : 
    1189             :         {
    1190           2 :             std::ofstream options_file;
    1191           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1192           1 :             CATCH_REQUIRE(options_file.good());
    1193           1 :             options_file <<
    1194             :                 "# Auto-generated\n"
    1195             : 
    1196             :                 "[foo]\n"
    1197             :                 "shortname=f\n"
    1198             :                 "default='Invalid Stuff'\n"
    1199             :                 "alias\n"      // name missing (no equal)
    1200             :                 "allowed=command-line\n"
    1201             :             ;
    1202             :         }
    1203             : 
    1204           1 :         char const * sub_cargv[] =
    1205             :         {
    1206             :             "tests/unittests/non_existant_alias",
    1207             :             "--verbose",
    1208             :             nullptr
    1209             :         };
    1210           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1211           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1212             : 
    1213           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1214             :                     , advgetopt::getopt_logic_error
    1215             :                     , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
    1216             :     CATCH_END_SECTION()
    1217             : 
    1218          14 :     CATCH_START_SECTION("non-existant alias")
    1219           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
    1220           1 :         tmpdir += "/shared/advgetopt";
    1221           2 :         std::stringstream ss;
    1222           1 :         ss << "mkdir -p " << tmpdir;
    1223           1 :         if(system(ss.str().c_str()) != 0)
    1224             :         {
    1225           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1226           0 :             exit(1);
    1227             :         }
    1228           2 :         std::string const options_filename(tmpdir + "/non-existant-alias.ini");
    1229             : 
    1230           1 :         advgetopt::option const options[] =
    1231             :         {
    1232             :             advgetopt::define_option(
    1233             :                   advgetopt::Name("verbose")
    1234             :                 , advgetopt::ShortName('v')
    1235             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1236             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1237             :             ),
    1238             :             advgetopt::end_options()
    1239             :         };
    1240             : 
    1241           1 :         advgetopt::options_environment options_environment;
    1242           1 :         options_environment.f_project_name = "non-existant-alias";
    1243           1 :         options_environment.f_options = options;
    1244           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1245           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1246           1 :         options_environment.f_environment_variable_name = nullptr;
    1247           1 :         options_environment.f_help_header = "Usage: test invalid validator specification";
    1248             : 
    1249             :         {
    1250           2 :             std::ofstream options_file;
    1251           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1252           1 :             CATCH_REQUIRE(options_file.good());
    1253           1 :             options_file <<
    1254             :                 "# Auto-generated\n"
    1255             : 
    1256             :                 "[foo]\n"
    1257             :                 "shortname=f\n"
    1258             :                 "default='Invalid Stuff'\n"
    1259             :                 "alias=bar\n"       // option "bar" missing
    1260             :                 "allowed=command-line\n"
    1261             :             ;
    1262             :         }
    1263             : 
    1264           1 :         char const * sub_cargv[] =
    1265             :         {
    1266             :             "tests/unittests/non_existant_alias",
    1267             :             "--verbose",
    1268             :             nullptr
    1269             :         };
    1270           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1271           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1272             : 
    1273           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1274             :                     , advgetopt::getopt_logic_error
    1275             :                     , Catch::Matchers::ExceptionMessage("getopt_logic_error: no option named \"bar\" to satisfy the alias of \"foo\"."));
    1276             :     CATCH_END_SECTION()
    1277          13 : }
    1278             : 
    1279             : 
    1280             : 
    1281             : 
    1282             : 
    1283             : 
    1284             : 
    1285             : 
    1286             : 
    1287             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13