LCOV - code coverage report
Current view: top level - tests - catch_options_files.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 493 516 95.5 %
Date: 2022-03-01 20:39:45 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             : 
     546           1 :             SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"1001 meters\" given to parameter --size is not considered valid.");
     547           1 :             SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"valid.cpp\" given to parameter --files is not considered valid.");
     548           1 :             SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"auto-build\" given to parameter --from is not considered valid.");
     549           1 :             SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"black\" given to parameter --more is not considered valid.");
     550           1 :             opt.parse_environment_variable();
     551           1 :             SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     552             :         }
     553             :     CATCH_END_SECTION()
     554             : 
     555          12 :     CATCH_START_SECTION("Check with validators in the definition")
     556           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     557           1 :         tmpdir += "/shared/advgetopt-validators-in-table";
     558           2 :         std::stringstream ss;
     559           1 :         ss << "mkdir -p " << tmpdir;
     560           1 :         if(system(ss.str().c_str()) != 0)
     561             :         {
     562           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     563           0 :             exit(1);
     564             :         }
     565           2 :         std::string const options_filename(tmpdir + "/unittest.ini");
     566             : 
     567           1 :         advgetopt::option const valid_options_from_file_list[] =
     568             :         {
     569             :             advgetopt::define_option(
     570             :                   advgetopt::Name("verbose")
     571             :                 , advgetopt::ShortName('v')
     572             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     573             :                 , advgetopt::Help("a verbose like option, select it or not.")
     574             :             ),
     575             :             advgetopt::define_option(
     576             :                   advgetopt::Name("size")
     577             :                 , advgetopt::ShortName('s')
     578             :                 , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED>())
     579             :                 , advgetopt::Help("Specify the size.")
     580             :                 , advgetopt::Validator("integer(0...100)")
     581             :                 , advgetopt::DefaultValue("31")
     582             :             ),
     583             :             advgetopt::define_option(
     584             :                   advgetopt::Name("files")
     585             :                 , advgetopt::ShortName('f')
     586             :                 , advgetopt::Help("List of file names")
     587             :                 , advgetopt::Validator("/.*\\.txt/i")
     588             :                 , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED, advgetopt::GETOPT_FLAG_MULTIPLE>())
     589             :             ),
     590             :             advgetopt::define_option(
     591             :                   advgetopt::Name("from")
     592             :                 , advgetopt::ShortName('F')
     593             :                 , advgetopt::Help("Request for the geographcal location representing the origin of the files; optionally you can specify the format")
     594             :                 , advgetopt::Validator("integer")
     595             :                 , advgetopt::Flags(advgetopt::all_flags<>())
     596             :             ),
     597             :             advgetopt::define_option(
     598             :                   advgetopt::Name("more")
     599             :                 , advgetopt::ShortName('m')
     600             :                 , advgetopt::Help("Allow for more stuff to be added")
     601             :                 , advgetopt::Validator("regex(\"purple|yellow|blue|red|green|orange|brown\")")
     602             :                 , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED, advgetopt::GETOPT_FLAG_SHOW_USAGE_ON_ERROR>())
     603             :                 , advgetopt::DefaultValue("More Stuff")
     604             :             ),
     605             :             advgetopt::end_options()
     606             :         };
     607             : 
     608           1 :         advgetopt::options_environment valid_options_from_file;
     609           1 :         valid_options_from_file.f_project_name = "unittest";
     610           1 :         valid_options_from_file.f_options = valid_options_from_file_list;
     611           1 :         valid_options_from_file.f_options_files_directory = tmpdir.c_str();
     612           1 :         valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     613           1 :         valid_options_from_file.f_help_header = "Usage: test valid options from file";
     614             : 
     615           1 :         snapdev::safe_setenv env("ADVGETOPT_TEST_OPTIONS"
     616             :                             , "--verbose"
     617             :                              " --more purple"
     618             :                              " -f left.txt center.txt right.txt"
     619             :                              " --size 19"
     620             :                              " --from"
     621           2 :                              " --output destination.txt");
     622             : 
     623             :         {
     624           2 :             std::ofstream options_file;
     625           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     626           1 :             CATCH_REQUIRE(options_file.good());
     627           1 :             options_file <<
     628             :                 "# Auto-generated\n"
     629             : 
     630             :                 "[output]\n"
     631             :                 "shortname=o\n"
     632             :                 "default=a.out\n"
     633             :                 "help=output file\n"
     634             :                 "allowed=environment-variable\n"
     635             :                 "required\n"
     636             : 
     637             :                 "[license]\n"
     638             :                 "shortname=l\n"
     639             :                 "help=show this test license\n"
     640             :                 "allowed=command-line\n"
     641             :                 "no-arguments\n"
     642             : 
     643             :                 "[licence]\n"
     644             :                 "alias=license\n"
     645             :                 "allowed=command-line\n"
     646             :                 "no-arguments\n"
     647             :             ;
     648             :         }
     649             : 
     650           1 :         char const * sub_cargv[] =
     651             :         {
     652             :             "tests/unittests/valid_options_files",
     653             :             "--verbose",
     654             :             "--licence",
     655             :             nullptr
     656             :         };
     657           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     658           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     659             : 
     660           2 :         advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
     661             : 
     662             :         // check that the result is valid
     663             : 
     664             :         // an invalid parameter, MUST NOT EXIST
     665           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     666           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     667             : 
     668             :         // the valid parameter
     669           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     670           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     671           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     672             : 
     673             :         // "--more"
     674           1 :         CATCH_REQUIRE(opt.is_defined("more"));
     675           1 :         CATCH_REQUIRE(opt.get_string("more") == "purple");
     676           1 :         CATCH_REQUIRE(opt.get_default("more") == "More Stuff");
     677           1 :         CATCH_REQUIRE(opt.size("more") == 1);
     678             : 
     679             :         // "--size <value>"
     680           1 :         CATCH_REQUIRE(opt.is_defined("size"));
     681           1 :         CATCH_REQUIRE(opt.get_string("size") == "19");
     682           1 :         CATCH_REQUIRE(opt.get_string("size", 0) == "19");
     683           1 :         CATCH_REQUIRE(opt.get_default("size") == "31");
     684           1 :         CATCH_REQUIRE(opt.size("size") == 1);
     685           1 :         CATCH_REQUIRE(opt.get_long("size") == 19);
     686             : 
     687             :         // "--files"
     688           1 :         CATCH_REQUIRE(opt.is_defined("files"));
     689           1 :         CATCH_REQUIRE(opt.get_string("files") == "left.txt");
     690           1 :         CATCH_REQUIRE(opt.get_string("files", 0) == "left.txt");
     691           1 :         CATCH_REQUIRE(opt.get_string("files", 1) == "center.txt");
     692           1 :         CATCH_REQUIRE(opt.get_string("files", 2) == "right.txt");
     693           1 :         CATCH_REQUIRE(opt.get_default("files").empty());
     694           1 :         CATCH_REQUIRE(opt.size("files") == 3);
     695             : 
     696             :         // "--from"
     697           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     698           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     699           1 :         CATCH_REQUIRE(opt.get_string("from") == "");
     700           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     701           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     702           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     703           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     704           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     705           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     706           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     707             : 
     708             :         // "--output"
     709           1 :         CATCH_REQUIRE(opt.is_defined("output"));
     710           1 :         CATCH_REQUIRE(opt.get_string("output") == "destination.txt"); // same as index = 0
     711           1 :         CATCH_REQUIRE(opt.get_string("output",  0) == "destination.txt");
     712           1 :         CATCH_REQUIRE(opt.get_default("output") == "a.out");
     713           1 :         CATCH_REQUIRE(opt.size("output") == 1);
     714             : 
     715             :         // "--from"
     716           1 :         CATCH_REQUIRE(opt.is_defined("license"));
     717           1 :         CATCH_REQUIRE(opt.get_string("license") == "");
     718           1 :         CATCH_REQUIRE(opt.get_default("license").empty());
     719           1 :         CATCH_REQUIRE(opt.size("license") == 1);
     720             : 
     721             :         // other parameters
     722           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     723           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     724             : 
     725           1 :         char const * sub_cargv2[] =
     726             :         {
     727             :             "this/is/ignored",
     728             :             "--from",
     729             :             "1001",
     730             :             nullptr
     731             :         };
     732           1 :         int const sub_argc2(sizeof(sub_cargv2) / sizeof(sub_cargv2[0]) - 1);
     733           1 :         char ** sub_argv2 = const_cast<char **>(sub_cargv2);
     734             : 
     735           1 :         opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     736             : 
     737             :         // "--from"
     738           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     739           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     740           1 :         CATCH_REQUIRE(opt.get_string("from") == "1001");
     741           1 :         CATCH_REQUIRE(opt.get_long("from") == 1001);
     742           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     743             : 
     744             :         // other parameters
     745           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     746           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     747             : 
     748             :         // keep the last value...
     749             :         //
     750           1 :         opt.parse_environment_variable();
     751             : 
     752             :         // "--from"
     753           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     754           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     755           1 :         CATCH_REQUIRE(opt.get_string("from") == "");
     756           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     757           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     758           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     759           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     760             : 
     761             :         // other parameters
     762           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     763           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     764             : 
     765             :         // a reset will restore the state
     766             :         //
     767           1 :         opt.reset();
     768             : 
     769             :         // the valid parameter
     770           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("verbose"));
     771           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     772           1 :         CATCH_REQUIRE(opt.size("verbose") == 0);
     773             : 
     774             :         // "--from"
     775           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("from"));
     776           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     777           1 :         CATCH_REQUIRE(opt.size("from") == 0);
     778             : 
     779           1 :         opt.parse_environment_variable();
     780           1 :         opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     781             : 
     782             :         // "--from"
     783           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     784           1 :         CATCH_REQUIRE(opt.get_string("from") == "1001");
     785           1 :         CATCH_REQUIRE(opt.get_long("from") == 1001);
     786           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     787           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     788             : 
     789             :         // other parameters
     790           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     791           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     792             : 
     793             :         // test that the validators do work here (i.e. generate errors as
     794             :         // expected when we use the wrong options.)
     795             :         //
     796           1 :         char const * sub_cargv3[] =
     797             :         {
     798             :             "this/is/ignored",
     799             :             "--size",
     800             :             "1001",
     801             :             "-f",
     802             :             "valid.cpp",
     803             :             "--from",
     804             :             "51",
     805             :             "--more",
     806             :             "black",
     807             :             nullptr
     808             :         };
     809           1 :         int const sub_argc3(sizeof(sub_cargv3) / sizeof(sub_cargv3[0]) - 1);
     810           1 :         char ** sub_argv3 = const_cast<char **>(sub_cargv3);
     811             : 
     812           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"1001\" given to parameter --size is not considered valid.");
     813           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"valid.cpp\" given to parameter --files is not considered valid.");
     814           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"black\" given to parameter --more is not considered valid.");
     815           1 :         opt.parse_arguments(sub_argc3, sub_argv3, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     816           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     817             :     CATCH_END_SECTION()
     818           6 : }
     819             : 
     820             : 
     821           9 : CATCH_TEST_CASE("invalid_options_files", "[options][invalid][files]")
     822             : {
     823          14 :     CATCH_START_SECTION("2+ section names")
     824           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     825           1 :         tmpdir += "/shared/advgetopt";
     826           2 :         std::stringstream ss;
     827           1 :         ss << "mkdir -p " << tmpdir;
     828           1 :         if(system(ss.str().c_str()) != 0)
     829             :         {
     830           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     831           0 :             exit(1);
     832             :         }
     833           2 :         std::string const options_filename(tmpdir + "/bad-section.ini");
     834             : 
     835           1 :         advgetopt::option const options[] =
     836             :         {
     837             :             advgetopt::define_option(
     838             :                   advgetopt::Name("verbose")
     839             :                 , advgetopt::ShortName('v')
     840             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     841             :                 , advgetopt::Help("a verbose like option, select it or not.")
     842             :             ),
     843             :             advgetopt::end_options()
     844             :         };
     845             : 
     846           1 :         advgetopt::options_environment options_environment;
     847           1 :         options_environment.f_project_name = "bad-section";
     848           1 :         options_environment.f_options = options;
     849           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
     850           1 :         options_environment.f_environment_variable_name = nullptr;
     851           1 :         options_environment.f_help_header = "Usage: test invalid section name";
     852             : 
     853             :         {
     854           2 :             std::ofstream options_file;
     855           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     856           1 :             CATCH_REQUIRE(options_file.good());
     857           1 :             options_file <<
     858             :                 "# Auto-generated\n"
     859             : 
     860             :                 "[invalid::name]\n"
     861             :                 "shortname=m\n"
     862             :                 "default='Invalid Stuff'\n"
     863             :                 "help=Testing that a section name can't include \"::\"\n"
     864             :                 "allowed=command-line,environment-variable,configuration-file\n"
     865             :             ;
     866             :         }
     867             : 
     868           1 :         char const * sub_cargv[] =
     869             :         {
     870             :             "tests/unittests/invalid_name_in_options_ini",
     871             :             "--verbose",
     872             :             nullptr
     873             :         };
     874           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     875           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     876             : 
     877           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     878             :                     "error: option name \"shortname\" cannot be added to"
     879             :                     " section \"invalid::name\" because this"
     880             :                     " configuration only accepts one section level.");
     881           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     882             :                     "error: option name \"default\" cannot be added to"
     883             :                     " section \"invalid::name\" because this"
     884             :                     " configuration only accepts one section level.");
     885           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     886             :                     "error: option name \"help\" cannot be added to"
     887             :                     " section \"invalid::name\" because this"
     888             :                     " configuration only accepts one section level.");
     889           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     890             :                     "error: option name \"allowed\" cannot be added to"
     891             :                     " section \"invalid::name\" because this"
     892             :                     " configuration only accepts one section level.");
     893           2 :         advgetopt::getopt::pointer_t opt(std::make_shared<advgetopt::getopt>(options_environment));
     894             :         try
     895             :         {
     896           1 :             opt->finish_parsing(sub_argc, sub_argv);
     897           0 :             CATCH_REQUIRE(false);   // the library is expected to throw here
     898             :         }
     899           2 :         catch(advgetopt::getopt_exit const & e)
     900             :         {
     901           1 :             CATCH_REQUIRE(e.code() == 1);
     902           1 :             CATCH_REQUIRE(e.what() == std::string("getopt_exception: errors were found on your command line, environment variable, or configuration file."));
     903             :         }
     904           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     905             : 
     906           1 :         CATCH_REQUIRE(opt->size("invalid::name::shortname") == 0);
     907           1 :         CATCH_REQUIRE(opt->size("shortname") == 0);
     908             :     CATCH_END_SECTION()
     909             : 
     910          14 :     CATCH_START_SECTION("short name too long")
     911           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     912           1 :         tmpdir += "/shared/advgetopt";
     913           2 :         std::stringstream ss;
     914           1 :         ss << "mkdir -p " << tmpdir;
     915           1 :         if(system(ss.str().c_str()) != 0)
     916             :         {
     917           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     918           0 :             exit(1);
     919             :         }
     920           2 :         std::string const options_filename(tmpdir + "/bad-shortname.ini");
     921             : 
     922           1 :         advgetopt::option const options[] =
     923             :         {
     924             :             advgetopt::define_option(
     925             :                   advgetopt::Name("verbose")
     926             :                 , advgetopt::ShortName('v')
     927             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     928             :                 , advgetopt::Help("a verbose like option, select it or not.")
     929             :             ),
     930             :             advgetopt::end_options()
     931             :         };
     932             : 
     933           1 :         advgetopt::options_environment options_environment;
     934           1 :         options_environment.f_project_name = "bad-shortname";
     935           1 :         options_environment.f_options = options;
     936           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
     937           1 :         options_environment.f_environment_variable_name = nullptr;
     938           1 :         options_environment.f_help_header = "Usage: test invalid shortname";
     939             : 
     940             :         {
     941           2 :             std::ofstream options_file;
     942           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     943           1 :             CATCH_REQUIRE(options_file.good());
     944           1 :             options_file <<
     945             :                 "# Auto-generated\n"
     946             : 
     947             :                 "[badname]\n"
     948             :                 "shortname=to\n"
     949             :                 "default='Invalid Stuff'\n"
     950             :                 "help=Testing that a shotname can't be 2 characters or more\n"
     951             :                 "allowed=command-line,environment-variable,configuration-file\n"
     952             :             ;
     953             :         }
     954             : 
     955           1 :         char const * sub_cargv[] =
     956             :         {
     957             :             "tests/unittests/invalid_name_in_options_ini",
     958             :             "--verbose",
     959             :             nullptr
     960             :         };
     961           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     962           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     963             : 
     964           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
     965             :                     , advgetopt::getopt_logic_error
     966             :                     , Catch::Matchers::ExceptionMessage(
     967             :                               "getopt_logic_error: option \"badname\" has an invalid short name in \""
     968             :                             + options_filename
     969             :                             + "\", it can't be more than one character."));
     970             :     CATCH_END_SECTION()
     971             : 
     972          14 :     CATCH_START_SECTION("missing ')' in validator specification")
     973           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     974           1 :         tmpdir += "/shared/advgetopt";
     975           2 :         std::stringstream ss;
     976           1 :         ss << "mkdir -p " << tmpdir;
     977           1 :         if(system(ss.str().c_str()) != 0)
     978             :         {
     979           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     980           0 :             exit(1);
     981             :         }
     982           2 :         std::string const options_filename(tmpdir + "/bad-validator-parenthesis.ini");
     983             : 
     984           1 :         advgetopt::option const options[] =
     985             :         {
     986             :             advgetopt::define_option(
     987             :                   advgetopt::Name("verbose")
     988             :                 , advgetopt::ShortName('v')
     989             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     990             :                 , advgetopt::Help("a verbose like option, select it or not.")
     991             :             ),
     992             :             advgetopt::end_options()
     993             :         };
     994             : 
     995           1 :         advgetopt::options_environment options_environment;
     996           1 :         options_environment.f_project_name = "bad-validator-parenthesis";
     997           1 :         options_environment.f_options = options;
     998           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
     999           1 :         options_environment.f_environment_variable_name = nullptr;
    1000           1 :         options_environment.f_help_header = "Usage: test invalid validator specification";
    1001             : 
    1002             :         {
    1003           2 :             std::ofstream options_file;
    1004           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1005           1 :             CATCH_REQUIRE(options_file.good());
    1006           1 :             options_file <<
    1007             :                 "# Auto-generated\n"
    1008             : 
    1009             :                 "[bad-validator]\n"
    1010             :                 "shortname=b\n"
    1011             :                 "default='Invalid Stuff'\n"
    1012             :                 "help=Testing that a validator with parenthesis must have the ')'\n"
    1013             :                 "validator=regex(\"missing ')'\"\n"
    1014             :                 "allowed=command-line,environment-variable,configuration-file\n"
    1015             :             ;
    1016             :         }
    1017             : 
    1018           1 :         char const * sub_cargv[] =
    1019             :         {
    1020             :             "tests/unittests/invalid_validator_specification",
    1021             :             "--verbose",
    1022             :             nullptr
    1023             :         };
    1024           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1025           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1026             : 
    1027           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1028             :                     , advgetopt::getopt_logic_error
    1029             :                     , Catch::Matchers::ExceptionMessage(
    1030             :                               "getopt_logic_error: invalid validator parameter definition: \"regex(\"missing ')'\"\", the ')' is missing."));
    1031             :     CATCH_END_SECTION()
    1032             : 
    1033          14 :     CATCH_START_SECTION("alias with help")
    1034           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
    1035           1 :         tmpdir += "/shared/advgetopt";
    1036           2 :         std::stringstream ss;
    1037           1 :         ss << "mkdir -p " << tmpdir;
    1038           1 :         if(system(ss.str().c_str()) != 0)
    1039             :         {
    1040           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1041           0 :             exit(1);
    1042             :         }
    1043           2 :         std::string const options_filename(tmpdir + "/alias-with-help.ini");
    1044             : 
    1045           1 :         advgetopt::option const options[] =
    1046             :         {
    1047             :             advgetopt::define_option(
    1048             :                   advgetopt::Name("verbose")
    1049             :                 , advgetopt::ShortName('v')
    1050             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1051             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1052             :             ),
    1053             :             advgetopt::end_options()
    1054             :         };
    1055             : 
    1056           1 :         advgetopt::options_environment options_environment;
    1057           1 :         options_environment.f_project_name = "alias-with-help";
    1058           1 :         options_environment.f_options = options;
    1059           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1060           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1061           1 :         options_environment.f_environment_variable_name = nullptr;
    1062           1 :         options_environment.f_help_header = "Usage: test invalid validator specification";
    1063             : 
    1064             :         {
    1065           2 :             std::ofstream options_file;
    1066           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1067           1 :             CATCH_REQUIRE(options_file.good());
    1068           1 :             options_file <<
    1069             :                 "# Auto-generated\n"
    1070             : 
    1071             :                 "[licence]\n"
    1072             :                 "shortname=l\n"
    1073             :                 "default='Invalid Stuff'\n"
    1074             :                 "alias=license\n"
    1075             :                 "help=Testing that an alias can't accept a help string\n"
    1076             :                 "allowed=command-line,environment-variable,configuration-file\n"
    1077             :             ;
    1078             :         }
    1079             : 
    1080           1 :         char const * sub_cargv[] =
    1081             :         {
    1082             :             "tests/unittests/invalid_alias_specification",
    1083             :             "--verbose",
    1084             :             nullptr
    1085             :         };
    1086           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1087           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1088             : 
    1089           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1090             :                     , advgetopt::getopt_logic_error
    1091             :                     , Catch::Matchers::ExceptionMessage(
    1092             :                               "getopt_logic_error: option \"licence\" is an alias and as such it can't include a help=... parameter in \""
    1093             :                             + options_filename
    1094             :                             + "\"."));
    1095             :     CATCH_END_SECTION()
    1096             : 
    1097          14 :     CATCH_START_SECTION("no-name alias")
    1098           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
    1099           1 :         tmpdir += "/shared/advgetopt";
    1100           2 :         std::stringstream ss;
    1101           1 :         ss << "mkdir -p " << tmpdir;
    1102           1 :         if(system(ss.str().c_str()) != 0)
    1103             :         {
    1104           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1105           0 :             exit(1);
    1106             :         }
    1107           2 :         std::string const options_filename(tmpdir + "/no-name-alias.ini");
    1108             : 
    1109           1 :         advgetopt::option const options[] =
    1110             :         {
    1111             :             advgetopt::define_option(
    1112             :                   advgetopt::Name("verbose")
    1113             :                 , advgetopt::ShortName('v')
    1114             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1115             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1116             :             ),
    1117             :             advgetopt::end_options()
    1118             :         };
    1119             : 
    1120           1 :         advgetopt::options_environment options_environment;
    1121           1 :         options_environment.f_project_name = "no-name-alias";
    1122           1 :         options_environment.f_options = options;
    1123           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1124           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1125           1 :         options_environment.f_environment_variable_name = nullptr;
    1126           1 :         options_environment.f_help_header = "Usage: test alias with no name specified";
    1127             : 
    1128             :         {
    1129           2 :             std::ofstream options_file;
    1130           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1131           1 :             CATCH_REQUIRE(options_file.good());
    1132           1 :             options_file <<
    1133             :                 "# Auto-generated\n"
    1134             : 
    1135             :                 "[foo]\n"
    1136             :                 "shortname=f\n"
    1137             :                 "default='Invalid Stuff'\n"
    1138             :                 "alias=\n"      // name missing (with an equal)
    1139             :                 "allowed=command-line\n"
    1140             :             ;
    1141             :         }
    1142             : 
    1143           1 :         char const * sub_cargv[] =
    1144             :         {
    1145             :             "tests/unittests/non_existant_alias",
    1146             :             "--verbose",
    1147             :             nullptr
    1148             :         };
    1149           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1150           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1151             : 
    1152           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1153             :                     , advgetopt::getopt_logic_error
    1154             :                     , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
    1155             :     CATCH_END_SECTION()
    1156             : 
    1157          14 :     CATCH_START_SECTION("no-name alias v2")
    1158           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
    1159           1 :         tmpdir += "/shared/advgetopt";
    1160           2 :         std::stringstream ss;
    1161           1 :         ss << "mkdir -p " << tmpdir;
    1162           1 :         if(system(ss.str().c_str()) != 0)
    1163             :         {
    1164           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1165           0 :             exit(1);
    1166             :         }
    1167           2 :         std::string const options_filename(tmpdir + "/no-name-alias-v2.ini");
    1168             : 
    1169           1 :         advgetopt::option const options[] =
    1170             :         {
    1171             :             advgetopt::define_option(
    1172             :                   advgetopt::Name("verbose")
    1173             :                 , advgetopt::ShortName('v')
    1174             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1175             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1176             :             ),
    1177             :             advgetopt::end_options()
    1178             :         };
    1179             : 
    1180           1 :         advgetopt::options_environment options_environment;
    1181           1 :         options_environment.f_project_name = "no-name-alias-v2";
    1182           1 :         options_environment.f_options = options;
    1183           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1184           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1185           1 :         options_environment.f_environment_variable_name = nullptr;
    1186           1 :         options_environment.f_help_header = "Usage: test alias with no name specified";
    1187             : 
    1188             :         {
    1189           2 :             std::ofstream options_file;
    1190           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1191           1 :             CATCH_REQUIRE(options_file.good());
    1192           1 :             options_file <<
    1193             :                 "# Auto-generated\n"
    1194             : 
    1195             :                 "[foo]\n"
    1196             :                 "shortname=f\n"
    1197             :                 "default='Invalid Stuff'\n"
    1198             :                 "alias\n"      // name missing (no equal)
    1199             :                 "allowed=command-line\n"
    1200             :             ;
    1201             :         }
    1202             : 
    1203           1 :         char const * sub_cargv[] =
    1204             :         {
    1205             :             "tests/unittests/non_existant_alias",
    1206             :             "--verbose",
    1207             :             nullptr
    1208             :         };
    1209           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1210           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1211             : 
    1212           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1213             :                     , advgetopt::getopt_logic_error
    1214             :                     , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
    1215             :     CATCH_END_SECTION()
    1216             : 
    1217          14 :     CATCH_START_SECTION("non-existant alias")
    1218           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
    1219           1 :         tmpdir += "/shared/advgetopt";
    1220           2 :         std::stringstream ss;
    1221           1 :         ss << "mkdir -p " << tmpdir;
    1222           1 :         if(system(ss.str().c_str()) != 0)
    1223             :         {
    1224           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1225           0 :             exit(1);
    1226             :         }
    1227           2 :         std::string const options_filename(tmpdir + "/non-existant-alias.ini");
    1228             : 
    1229           1 :         advgetopt::option const options[] =
    1230             :         {
    1231             :             advgetopt::define_option(
    1232             :                   advgetopt::Name("verbose")
    1233             :                 , advgetopt::ShortName('v')
    1234             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1235             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1236             :             ),
    1237             :             advgetopt::end_options()
    1238             :         };
    1239             : 
    1240           1 :         advgetopt::options_environment options_environment;
    1241           1 :         options_environment.f_project_name = "non-existant-alias";
    1242           1 :         options_environment.f_options = options;
    1243           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1244           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1245           1 :         options_environment.f_environment_variable_name = nullptr;
    1246           1 :         options_environment.f_help_header = "Usage: test invalid validator specification";
    1247             : 
    1248             :         {
    1249           2 :             std::ofstream options_file;
    1250           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1251           1 :             CATCH_REQUIRE(options_file.good());
    1252           1 :             options_file <<
    1253             :                 "# Auto-generated\n"
    1254             : 
    1255             :                 "[foo]\n"
    1256             :                 "shortname=f\n"
    1257             :                 "default='Invalid Stuff'\n"
    1258             :                 "alias=bar\n"       // option "bar" missing
    1259             :                 "allowed=command-line\n"
    1260             :             ;
    1261             :         }
    1262             : 
    1263           1 :         char const * sub_cargv[] =
    1264             :         {
    1265             :             "tests/unittests/non_existant_alias",
    1266             :             "--verbose",
    1267             :             nullptr
    1268             :         };
    1269           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1270           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1271             : 
    1272           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1273             :                     , advgetopt::getopt_logic_error
    1274             :                     , Catch::Matchers::ExceptionMessage("getopt_logic_error: no option named \"bar\" to satisfy the alias of \"foo\"."));
    1275             :     CATCH_END_SECTION()
    1276          13 : }
    1277             : 
    1278             : 
    1279             : 
    1280             : 
    1281             : 
    1282             : 
    1283             : 
    1284             : 
    1285             : 
    1286             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13