LCOV - code coverage report
Current view: top level - tests - options_files.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 490 512 95.7 %
Date: 2019-07-15 03:11:49 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Files:
       3             :  *    tests/options_files.cpp
       4             :  *
       5             :  * License:
       6             :  *    Copyright (c) 2006-2019  Made to Order Software Corp.  All Rights Reserved
       7             :  *
       8             :  *    https://snapwebsites.org/
       9             :  *    contact@m2osw.com
      10             :  *
      11             :  *    This program is free software; you can redistribute it and/or modify
      12             :  *    it under the terms of the GNU General Public License as published by
      13             :  *    the Free Software Foundation; either version 2 of the License, or
      14             :  *    (at your option) any later version.
      15             :  *
      16             :  *    This program is distributed in the hope that it will be useful,
      17             :  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :  *    GNU General Public License for more details.
      20             :  *
      21             :  *    You should have received a copy of the GNU General Public License along
      22             :  *    with this program; if not, write to the Free Software Foundation, Inc.,
      23             :  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      24             :  *
      25             :  * Authors:
      26             :  *    Alexis Wilke   alexis@m2osw.com
      27             :  */
      28             : 
      29             : // self
      30             : //
      31             : #include "main.h"
      32             : 
      33             : // advgetopt lib
      34             : //
      35             : #include <advgetopt/exception.h>
      36             : 
      37             : // snapdev lib
      38             : //
      39             : #include <snapdev/safe_setenv.h>
      40             : 
      41             : // C++ lib
      42             : //
      43             : #include <fstream>
      44             : 
      45             : 
      46             : 
      47             : 
      48           8 : CATCH_TEST_CASE("valid_options_files", "[options][valid][files]")
      49             : {
      50          12 :     CATCH_START_SECTION("Check the default path with a nullptr (not a very good test, though)")
      51             :         advgetopt::option const options[] =
      52             :         {
      53             :             advgetopt::define_option(
      54             :                   advgetopt::Name("verbose")
      55             :                 , advgetopt::ShortName('v')
      56             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
      57             :                 , advgetopt::Help("a verbose like option, select it or not.")
      58             :             ),
      59             :             advgetopt::end_options()
      60           1 :         };
      61             : 
      62           1 :         advgetopt::options_environment options_env;
      63           1 :         options_env.f_project_name = "this-is-the-name-of-a-test-project-which-wont-ever-exist";
      64           1 :         options_env.f_options = options;
      65           1 :         options_env.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
      66           1 :         options_env.f_help_header = "Usage: test valid options from file";
      67             : 
      68             :         char const * sub_cargv[] =
      69             :         {
      70             :             "tests/unittests/no_file_to_load",
      71             :             "--verbose",
      72             :             nullptr
      73           1 :         };
      74           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
      75           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
      76             : 
      77           2 :         advgetopt::getopt opt(options_env, sub_argc, sub_argv);
      78             : 
      79             :         // check that the result is valid
      80             : 
      81             :         // an invalid parameter, MUST NOT EXIST
      82           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
      83           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
      84             : 
      85             :         // the valid parameter
      86           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
      87           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
      88           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
      89             : 
      90             :         // other parameters
      91           1 :         CATCH_REQUIRE(opt.get_program_name() == "no_file_to_load");
      92           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/no_file_to_load");
      93             :     CATCH_END_SECTION()
      94             : 
      95          12 :     CATCH_START_SECTION("Check the default path with an empty string (not a very good test, though)")
      96             :         advgetopt::option const options[] =
      97             :         {
      98             :             advgetopt::define_option(
      99             :                   advgetopt::Name("verbose")
     100             :                 , advgetopt::ShortName('v')
     101             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     102             :                 , advgetopt::Help("a verbose like option, select it or not.")
     103             :             ),
     104             :             advgetopt::end_options()
     105           1 :         };
     106             : 
     107           1 :         advgetopt::options_environment options_env;
     108           1 :         options_env.f_project_name = "this-is-the-name-of-a-test-project-which-wont-ever-exist";
     109           1 :         options_env.f_options = options;
     110           1 :         options_env.f_options_files_directory = "";
     111           1 :         options_env.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     112           1 :         options_env.f_help_header = "Usage: test valid options from file";
     113             : 
     114             :         char const * sub_cargv[] =
     115             :         {
     116             :             "tests/unittests/no_file_to_load",
     117             :             "--verbose",
     118             :             nullptr
     119           1 :         };
     120           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     121           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     122             : 
     123           2 :         advgetopt::getopt opt(options_env, sub_argc, sub_argv);
     124             : 
     125             :         // check that the result is valid
     126             : 
     127             :         // an invalid parameter, MUST NOT EXIST
     128           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     129           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     130             : 
     131             :         // the valid parameter
     132           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     133           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     134           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     135             : 
     136             :         // other parameters
     137           1 :         CATCH_REQUIRE(opt.get_program_name() == "no_file_to_load");
     138           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/no_file_to_load");
     139             :     CATCH_END_SECTION()
     140             : 
     141          12 :     CATCH_START_SECTION("Check the parsing of a valid options.ini file")
     142             :         // create a file and make sure it's not read if the project name
     143             :         // is empty
     144             :         //
     145           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
     146           1 :         tmpdir += "/shared/advgetopt";
     147           2 :         std::stringstream ss;
     148           1 :         ss << "mkdir -p " << tmpdir;
     149           1 :         if(system(ss.str().c_str()) != 0)
     150             :         {
     151           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     152           0 :             exit(1);
     153             :         }
     154           2 :         std::string const options_filename(tmpdir + "/no-project-name.ini");
     155             : 
     156             :         advgetopt::option const valid_options_from_file_list[] =
     157             :         {
     158             :             advgetopt::define_option(
     159             :                   advgetopt::Name("verbose")
     160             :                 , advgetopt::ShortName('v')
     161             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     162             :                 , advgetopt::Help("a verbose like option, select it or not.")
     163             :             ),
     164             :             advgetopt::end_options()
     165           1 :         };
     166             : 
     167           1 :         advgetopt::options_environment valid_options_from_file;
     168           1 :         valid_options_from_file.f_project_name = nullptr;
     169           1 :         valid_options_from_file.f_options = valid_options_from_file_list;
     170           1 :         valid_options_from_file.f_options_files_directory = tmpdir.c_str();
     171           1 :         valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     172           1 :         valid_options_from_file.f_help_header = "Usage: test valid options from file";
     173             : 
     174             :         {
     175           2 :             std::ofstream options_file;
     176           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     177           1 :             CATCH_REQUIRE(options_file.good());
     178             :             options_file <<
     179             :                 "# Auto-generated\n"
     180             : 
     181             :                 "[no-project-name]\n"
     182             :                 "shortname=n\n"
     183             :                 "default='inexistent'\n"
     184             :                 "help=Testing that this doesn't get loaded\n"
     185             :                 "allowed=command-line,environment-variable,configuration-file\n"
     186           1 :             ;
     187             :         }
     188             : 
     189             :         char const * sub_cargv[] =
     190             :         {
     191             :             "tests/unittests/file_not_loaded",
     192             :             "--verbose",
     193             :             nullptr
     194           1 :         };
     195           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     196           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     197             : 
     198           2 :         advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
     199             : 
     200             :         // check that the result is valid
     201             : 
     202             :         // an invalid parameter, MUST NOT EXIST
     203           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     204           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     205             : 
     206             :         // the valid parameter
     207           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     208           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     209           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     210             : 
     211             :         // "--no-project-name"
     212           1 :         CATCH_REQUIRE(opt.get_option("no-project-name") == nullptr);
     213           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("no-project-name"));
     214             : 
     215             :         // other parameters
     216           1 :         CATCH_REQUIRE(opt.get_program_name() == "file_not_loaded");
     217           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/file_not_loaded");
     218             :     CATCH_END_SECTION()
     219             : 
     220          12 :     CATCH_START_SECTION("Project name is an empty string")
     221             :         // create a file and make sure it's not read if the project name
     222             :         // is empty
     223             :         //
     224           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
     225           1 :         tmpdir += "/shared/advgetopt";
     226           2 :         std::stringstream ss;
     227           1 :         ss << "mkdir -p " << tmpdir;
     228           1 :         if(system(ss.str().c_str()) != 0)
     229             :         {
     230           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     231           0 :             exit(1);
     232             :         }
     233           2 :         std::string const options_filename(tmpdir + "/empty-string.ini");
     234             : 
     235             :         advgetopt::option const valid_options_from_file_list[] =
     236             :         {
     237             :             advgetopt::define_option(
     238             :                   advgetopt::Name("verbose")
     239             :                 , advgetopt::ShortName('v')
     240             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     241             :                 , advgetopt::Help("a verbose like option, select it or not.")
     242             :             ),
     243             :             advgetopt::end_options()
     244           1 :         };
     245             : 
     246           1 :         advgetopt::options_environment valid_options_from_file;
     247           1 :         valid_options_from_file.f_project_name = "";
     248           1 :         valid_options_from_file.f_options = valid_options_from_file_list;
     249           1 :         valid_options_from_file.f_options_files_directory = tmpdir.c_str();
     250           1 :         valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     251           1 :         valid_options_from_file.f_help_header = "Usage: test valid options from file";
     252             : 
     253             :         {
     254           2 :             std::ofstream options_file;
     255           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     256           1 :             CATCH_REQUIRE(options_file.good());
     257             :             options_file <<
     258             :                 "# Auto-generated\n"
     259             : 
     260             :                 "[no-project-name]\n"
     261             :                 "shortname=n\n"
     262             :                 "default='inexistent'\n"
     263             :                 "help=Testing that this doesn't get loaded\n"
     264             :                 "allowed=command-line,environment-variable,configuration-file\n"
     265           1 :             ;
     266             :         }
     267             : 
     268             :         char const * sub_cargv[] =
     269             :         {
     270             :             "tests/unittests/file_not_loaded",
     271             :             "--verbose",
     272             :             nullptr
     273           1 :         };
     274           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     275           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     276             : 
     277           2 :         advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
     278             : 
     279             :         // check that the result is valid
     280             : 
     281             :         // an invalid parameter, MUST NOT EXIST
     282           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     283           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     284             : 
     285             :         // the valid parameter
     286           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     287           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     288           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     289             : 
     290             :         // "--no-project-name"
     291           1 :         CATCH_REQUIRE(opt.get_option("no-project-name") == nullptr);
     292           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("no-project-name"));
     293             : 
     294             :         // other parameters
     295           1 :         CATCH_REQUIRE(opt.get_program_name() == "file_not_loaded");
     296           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/file_not_loaded");
     297             :     CATCH_END_SECTION()
     298             : 
     299          12 :     CATCH_START_SECTION("Check the parsing of a valid options.ini file")
     300           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
     301           1 :         tmpdir += "/shared/advgetopt";
     302           2 :         std::stringstream ss;
     303           1 :         ss << "mkdir -p " << tmpdir;
     304           1 :         if(system(ss.str().c_str()) != 0)
     305             :         {
     306           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     307           0 :             exit(1);
     308             :         }
     309           2 :         std::string const options_filename(tmpdir + "/unittest.ini");
     310             : 
     311             :         advgetopt::option const valid_options_from_file_list[] =
     312             :         {
     313             :             advgetopt::define_option(
     314             :                   advgetopt::Name("verbose")
     315             :                 , advgetopt::ShortName('v')
     316             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     317             :                 , advgetopt::Help("a verbose like option, select it or not.")
     318             :             ),
     319             :             advgetopt::end_options()
     320           1 :         };
     321             : 
     322           1 :         advgetopt::options_environment valid_options_from_file;
     323           1 :         valid_options_from_file.f_project_name = "unittest";
     324           1 :         valid_options_from_file.f_options = valid_options_from_file_list;
     325           1 :         valid_options_from_file.f_options_files_directory = tmpdir.c_str();
     326           1 :         valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
     327           1 :         valid_options_from_file.f_help_header = "Usage: test valid options from file";
     328             : 
     329             :         snap::safe_setenv env("ADVGETOPT_TEST_OPTIONS"
     330             :                             , "--verbose"
     331             :                              " --more purple"
     332             :                              " -f left.txt center.txt right.txt"
     333             :                              " --size 519"
     334             :                              " --from"
     335           2 :                              " --output destination.txt");
     336             : 
     337             :         {
     338           2 :             std::ofstream options_file;
     339           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     340           1 :             CATCH_REQUIRE(options_file.good());
     341             :             options_file <<
     342             :                 "# Auto-generated\n"
     343             : 
     344             :                 "[more]\n"
     345             :                 "shortname=m\n"
     346             :                 "default='More Stuff'\n"
     347             :                 "help=Allow for more stuff to be added\n"
     348             :                 "validator=regex(\"purple|yellow|blue|red|green|orange|brown\")\n"
     349             :                 "allowed=command-line,environment-variable,configuration-file\n"
     350             :                 "show-usage-on-error\n"
     351             :                 "required\n"
     352             : 
     353             :                 "[size]\n"
     354             :                 "shortname=s\n"
     355             :                 "help=Specify the size\n"
     356             :                 "validator=/[0-9]+/\n"
     357             :                 "allowed=environment-variable,configuration-file\n"
     358             :                 "default=31\n"
     359             :                 "required\n"
     360             : 
     361             :                 "[files]\n"
     362             :                 "shortname=f\n"
     363             :                 "help=List of file names\n"
     364             :                 "validator=/.*\\.txt/i\n"
     365             :                 "allowed=command-line,environment-variable\n"
     366             :                 "multiple\n"
     367             :                 "required\n"
     368             : 
     369             :                 "[from]\n"
     370             :                 "shortname=F\n"
     371             :                 "help=Request for the geographcal location representing the origin of the files; optionally you can specify the format\n"
     372             :                 "validator=integer\n"
     373             :                 "allowed=command-line,environment-variable,configuration-file\n"
     374             : 
     375             :                 "[output]\n"
     376             :                 "shortname=o\n"
     377             :                 "default=a.out\n"
     378             :                 "help=output file\n"
     379             :                 "allowed=environment-variable\n"
     380             :                 "required\n"
     381             : 
     382             :                 "[license]\n"
     383             :                 "shortname=l\n"
     384             :                 "help=show this test license\n"
     385             :                 "allowed=command-line\n"
     386             :                 "no-arguments\n"
     387             : 
     388             :                 "[licence]\n"
     389             :                 "alias=license\n"
     390             :                 "allowed=command-line\n"
     391             :                 "no-arguments\n"
     392           1 :             ;
     393             :         }
     394             : 
     395             :         char const * sub_cargv[] =
     396             :         {
     397             :             "tests/unittests/valid_options_files",
     398             :             "--verbose",
     399             :             "--licence",
     400             :             nullptr
     401           1 :         };
     402           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     403           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     404             : 
     405           2 :         advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
     406             : 
     407             :         // check that the result is valid
     408             : 
     409             :         // an invalid parameter, MUST NOT EXIST
     410           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
     411           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
     412             : 
     413             :         // the valid parameter
     414           1 :         CATCH_REQUIRE(opt.is_defined("verbose"));
     415           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     416           1 :         CATCH_REQUIRE(opt.size("verbose") == 1);
     417             : 
     418             :         // "--more"
     419           1 :         CATCH_REQUIRE(opt.is_defined("more"));
     420           1 :         CATCH_REQUIRE(opt.get_string("more") == "purple");
     421           1 :         CATCH_REQUIRE(opt.get_default("more") == "More Stuff");
     422           1 :         CATCH_REQUIRE(opt.size("more") == 1);
     423             : 
     424             :         // "--size <value>"
     425           1 :         CATCH_REQUIRE(opt.is_defined("size"));
     426           1 :         CATCH_REQUIRE(opt.get_string("size") == "519");
     427           1 :         CATCH_REQUIRE(opt.get_string("size", 0) == "519");
     428           1 :         CATCH_REQUIRE(opt.get_default("size") == "31");
     429           1 :         CATCH_REQUIRE(opt.size("size") == 1);
     430           1 :         CATCH_REQUIRE(opt.get_long("size") == 519);
     431             : 
     432             :         // "--files"
     433           1 :         CATCH_REQUIRE(opt.is_defined("files"));
     434           1 :         CATCH_REQUIRE(opt.get_string("files") == "left.txt");
     435           1 :         CATCH_REQUIRE(opt.get_string("files", 0) == "left.txt");
     436           1 :         CATCH_REQUIRE(opt.get_string("files", 1) == "center.txt");
     437           1 :         CATCH_REQUIRE(opt.get_string("files", 2) == "right.txt");
     438           1 :         CATCH_REQUIRE(opt.get_default("files").empty());
     439           1 :         CATCH_REQUIRE(opt.size("files") == 3);
     440             : 
     441             :         // "--from"
     442           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     443           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     444           1 :         CATCH_REQUIRE(opt.get_string("from") == "");
     445           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     446           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     447           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     448           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     449             : 
     450             :         // "--output"
     451           1 :         CATCH_REQUIRE(opt.is_defined("output"));
     452           1 :         CATCH_REQUIRE(opt.get_string("output") == "destination.txt"); // same as index = 0
     453           1 :         CATCH_REQUIRE(opt.get_string("output",  0) == "destination.txt");
     454           1 :         CATCH_REQUIRE(opt.get_default("output") == "a.out");
     455           1 :         CATCH_REQUIRE(opt.size("output") == 1);
     456             : 
     457             :         // "--from"
     458           1 :         CATCH_REQUIRE(opt.is_defined("license"));
     459           1 :         CATCH_REQUIRE(opt.get_string("license") == "");
     460           1 :         CATCH_REQUIRE(opt.get_default("license").empty());
     461           1 :         CATCH_REQUIRE(opt.size("license") == 1);
     462             : 
     463             :         // other parameters
     464           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     465           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     466             : 
     467             :         char const * sub_cargv2[] =
     468             :         {
     469             :             "this/is/ignored",
     470             :             "--from",
     471             :             "1001",
     472             :             nullptr
     473           1 :         };
     474           1 :         int const sub_argc2(sizeof(sub_cargv2) / sizeof(sub_cargv2[0]) - 1);
     475           1 :         char ** sub_argv2 = const_cast<char **>(sub_cargv2);
     476             : 
     477           1 :         opt.parse_arguments(sub_argc2, sub_argv2);
     478             : 
     479             :         // "--from"
     480           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     481           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     482           1 :         CATCH_REQUIRE(opt.get_string("from") == "1001");
     483           1 :         CATCH_REQUIRE(opt.get_long("from") == 1001);
     484           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     485             : 
     486             :         // other parameters
     487           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     488           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     489             : 
     490             :         // keep the last value...
     491             :         //
     492           1 :         opt.parse_environment_variable();
     493             : 
     494             :         // "--from"
     495           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     496           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     497           1 :         CATCH_REQUIRE(opt.get_string("from") == "");
     498           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
     499           1 :         CATCH_REQUIRE(opt.get_long("from") == -1);
     500           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     501           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     502             : 
     503             :         // other parameters
     504           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     505           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     506             : 
     507             :         // a reset will restore the state
     508             :         //
     509           1 :         opt.reset();
     510             : 
     511             :         // the valid parameter
     512           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("verbose"));
     513           1 :         CATCH_REQUIRE(opt.get_default("verbose").empty());
     514           1 :         CATCH_REQUIRE(opt.size("verbose") == 0);
     515             : 
     516             :         // "--from"
     517           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("from"));
     518           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     519           1 :         CATCH_REQUIRE(opt.size("from") == 0);
     520             : 
     521           1 :         opt.parse_environment_variable();
     522           1 :         opt.parse_arguments(sub_argc2, sub_argv2);
     523             : 
     524             :         // "--from"
     525           1 :         CATCH_REQUIRE(opt.is_defined("from"));
     526           1 :         CATCH_REQUIRE(opt.get_string("from") == "1001");
     527           1 :         CATCH_REQUIRE(opt.get_long("from") == 1001);
     528           1 :         CATCH_REQUIRE(opt.get_default("from").empty());
     529           1 :         CATCH_REQUIRE(opt.size("from") == 1);
     530             : 
     531             :         // other parameters
     532           1 :         CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
     533           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
     534             : 
     535             : 
     536             :         // test that the validators do work here (i.e. generate errors as
     537             :         // expected when we use the wrong options.)
     538             :         //
     539             :         {
     540             :             snap::safe_setenv subenv("ADVGETOPT_TEST_OPTIONS"
     541             :                                 , "--verbose"
     542             :                                  " --size '1001 meters'"
     543             :                                  " -f valid.cpp"
     544             :                                  " --from auto-build"
     545           2 :                                  " --more black");
     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             :         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           1 :         };
     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             :         snap::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             :             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           1 :             ;
     649             :         }
     650             : 
     651             :         char const * sub_cargv[] =
     652             :         {
     653             :             "tests/unittests/valid_options_files",
     654             :             "--verbose",
     655             :             "--licence",
     656             :             nullptr
     657           1 :         };
     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             :         char const * sub_cargv2[] =
     727             :         {
     728             :             "this/is/ignored",
     729             :             "--from",
     730             :             "1001",
     731             :             nullptr
     732           1 :         };
     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);
     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);
     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             :         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           1 :         };
     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);
     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             :         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           1 :         };
     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             :             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           1 :             ;
     867             :         }
     868             : 
     869             :         char const * sub_cargv[] =
     870             :         {
     871             :             "tests/unittests/invalid_name_in_options_ini",
     872             :             "--verbose",
     873             :             nullptr
     874           1 :         };
     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           2 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     879             :                     "error: option name \"shortname\" cannot be added to"
     880             :                     " section \"invalid::name\" because this"
     881           1 :                     " configuration only accepts one section level.");
     882           2 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     883             :                     "error: option name \"default\" cannot be added to"
     884             :                     " section \"invalid::name\" because this"
     885           1 :                     " configuration only accepts one section level.");
     886           2 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     887             :                     "error: option name \"help\" cannot be added to"
     888             :                     " section \"invalid::name\" because this"
     889           1 :                     " configuration only accepts one section level.");
     890           2 :         SNAP_CATCH2_NAMESPACE::push_expected_log(
     891             :                     "error: option name \"allowed\" cannot be added to"
     892             :                     " section \"invalid::name\" because this"
     893           1 :                     " configuration only accepts one section level.");
     894           2 :         advgetopt::getopt::pointer_t opt(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv));
     895           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     896             : 
     897           1 :         CATCH_REQUIRE(opt->size("invalid::name::shortname") == 0);
     898           1 :         CATCH_REQUIRE(opt->size("shortname") == 0);
     899             :     CATCH_END_SECTION()
     900             : 
     901          14 :     CATCH_START_SECTION("short name too long")
     902           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
     903           1 :         tmpdir += "/shared/advgetopt";
     904           2 :         std::stringstream ss;
     905           1 :         ss << "mkdir -p " << tmpdir;
     906           1 :         if(system(ss.str().c_str()) != 0)
     907             :         {
     908           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     909           0 :             exit(1);
     910             :         }
     911           2 :         std::string const options_filename(tmpdir + "/bad-shortname.ini");
     912             : 
     913             :         advgetopt::option const options[] =
     914             :         {
     915             :             advgetopt::define_option(
     916             :                   advgetopt::Name("verbose")
     917             :                 , advgetopt::ShortName('v')
     918             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     919             :                 , advgetopt::Help("a verbose like option, select it or not.")
     920             :             ),
     921             :             advgetopt::end_options()
     922           1 :         };
     923             : 
     924           1 :         advgetopt::options_environment options_environment;
     925           1 :         options_environment.f_project_name = "bad-shortname";
     926           1 :         options_environment.f_options = options;
     927           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
     928           1 :         options_environment.f_environment_variable_name = nullptr;
     929           1 :         options_environment.f_help_header = "Usage: test invalid shortname";
     930             : 
     931             :         {
     932           2 :             std::ofstream options_file;
     933           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     934           1 :             CATCH_REQUIRE(options_file.good());
     935             :             options_file <<
     936             :                 "# Auto-generated\n"
     937             : 
     938             :                 "[badname]\n"
     939             :                 "shortname=to\n"
     940             :                 "default='Invalid Stuff'\n"
     941             :                 "help=Testing that a shotname can't be 2 characters or more\n"
     942             :                 "allowed=command-line,environment-variable,configuration-file\n"
     943           1 :             ;
     944             :         }
     945             : 
     946             :         char const * sub_cargv[] =
     947             :         {
     948             :             "tests/unittests/invalid_name_in_options_ini",
     949             :             "--verbose",
     950             :             nullptr
     951           1 :         };
     952           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
     953           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
     954             : 
     955           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
     956             :                     , advgetopt::getopt_exception_logic
     957             :                     , Catch::Matchers::ExceptionMessage(
     958             :                               "option \"badname\" has an invalid short name in \""
     959             :                             + options_filename
     960             :                             + "\", it can't be more than one character."));
     961             :     CATCH_END_SECTION()
     962             : 
     963          14 :     CATCH_START_SECTION("missing ')' in validator specification")
     964           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
     965           1 :         tmpdir += "/shared/advgetopt";
     966           2 :         std::stringstream ss;
     967           1 :         ss << "mkdir -p " << tmpdir;
     968           1 :         if(system(ss.str().c_str()) != 0)
     969             :         {
     970           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
     971           0 :             exit(1);
     972             :         }
     973           2 :         std::string const options_filename(tmpdir + "/bad-validator-parenthesis.ini");
     974             : 
     975             :         advgetopt::option const options[] =
     976             :         {
     977             :             advgetopt::define_option(
     978             :                   advgetopt::Name("verbose")
     979             :                 , advgetopt::ShortName('v')
     980             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
     981             :                 , advgetopt::Help("a verbose like option, select it or not.")
     982             :             ),
     983             :             advgetopt::end_options()
     984           1 :         };
     985             : 
     986           1 :         advgetopt::options_environment options_environment;
     987           1 :         options_environment.f_project_name = "bad-validator-parenthesis";
     988           1 :         options_environment.f_options = options;
     989           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
     990           1 :         options_environment.f_environment_variable_name = nullptr;
     991           1 :         options_environment.f_help_header = "Usage: test invalid validator specification";
     992             : 
     993             :         {
     994           2 :             std::ofstream options_file;
     995           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
     996           1 :             CATCH_REQUIRE(options_file.good());
     997             :             options_file <<
     998             :                 "# Auto-generated\n"
     999             : 
    1000             :                 "[bad-validator]\n"
    1001             :                 "shortname=b\n"
    1002             :                 "default='Invalid Stuff'\n"
    1003             :                 "help=Testing that a validator with parenthesis must have the ')'\n"
    1004             :                 "validator=regex(\"missing ')'\"\n"
    1005             :                 "allowed=command-line,environment-variable,configuration-file\n"
    1006           1 :             ;
    1007             :         }
    1008             : 
    1009             :         char const * sub_cargv[] =
    1010             :         {
    1011             :             "tests/unittests/invalid_validator_specification",
    1012             :             "--verbose",
    1013             :             nullptr
    1014           1 :         };
    1015           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1016           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1017             : 
    1018           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1019             :                     , advgetopt::getopt_exception_logic
    1020             :                     , Catch::Matchers::ExceptionMessage(
    1021             :                               "invalid validator parameter definition: \"regex(\"missing ')'\"\", the ')' is missing."));
    1022             :     CATCH_END_SECTION()
    1023             : 
    1024          14 :     CATCH_START_SECTION("alias with help")
    1025           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
    1026           1 :         tmpdir += "/shared/advgetopt";
    1027           2 :         std::stringstream ss;
    1028           1 :         ss << "mkdir -p " << tmpdir;
    1029           1 :         if(system(ss.str().c_str()) != 0)
    1030             :         {
    1031           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1032           0 :             exit(1);
    1033             :         }
    1034           2 :         std::string const options_filename(tmpdir + "/alias-with-help.ini");
    1035             : 
    1036             :         advgetopt::option const options[] =
    1037             :         {
    1038             :             advgetopt::define_option(
    1039             :                   advgetopt::Name("verbose")
    1040             :                 , advgetopt::ShortName('v')
    1041             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1042             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1043             :             ),
    1044             :             advgetopt::end_options()
    1045           1 :         };
    1046             : 
    1047           1 :         advgetopt::options_environment options_environment;
    1048           1 :         options_environment.f_project_name = "alias-with-help";
    1049           1 :         options_environment.f_options = options;
    1050           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1051           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1052           1 :         options_environment.f_environment_variable_name = nullptr;
    1053           1 :         options_environment.f_help_header = "Usage: test invalid validator specification";
    1054             : 
    1055             :         {
    1056           2 :             std::ofstream options_file;
    1057           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1058           1 :             CATCH_REQUIRE(options_file.good());
    1059             :             options_file <<
    1060             :                 "# Auto-generated\n"
    1061             : 
    1062             :                 "[licence]\n"
    1063             :                 "shortname=l\n"
    1064             :                 "default='Invalid Stuff'\n"
    1065             :                 "alias=license\n"
    1066             :                 "help=Testing that an alias can't accept a help string\n"
    1067             :                 "allowed=command-line,environment-variable,configuration-file\n"
    1068           1 :             ;
    1069             :         }
    1070             : 
    1071             :         char const * sub_cargv[] =
    1072             :         {
    1073             :             "tests/unittests/invalid_alias_specification",
    1074             :             "--verbose",
    1075             :             nullptr
    1076           1 :         };
    1077           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1078           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1079             : 
    1080           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1081             :                     , advgetopt::getopt_exception_logic
    1082             :                     , Catch::Matchers::ExceptionMessage(
    1083             :                               "option \"licence\" is an alias and as such it can't include a help=... parameter in \""
    1084             :                             + options_filename
    1085             :                             + "\"."));
    1086             :     CATCH_END_SECTION()
    1087             : 
    1088          14 :     CATCH_START_SECTION("no-name alias")
    1089           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
    1090           1 :         tmpdir += "/shared/advgetopt";
    1091           2 :         std::stringstream ss;
    1092           1 :         ss << "mkdir -p " << tmpdir;
    1093           1 :         if(system(ss.str().c_str()) != 0)
    1094             :         {
    1095           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1096           0 :             exit(1);
    1097             :         }
    1098           2 :         std::string const options_filename(tmpdir + "/no-name-alias.ini");
    1099             : 
    1100             :         advgetopt::option const options[] =
    1101             :         {
    1102             :             advgetopt::define_option(
    1103             :                   advgetopt::Name("verbose")
    1104             :                 , advgetopt::ShortName('v')
    1105             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1106             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1107             :             ),
    1108             :             advgetopt::end_options()
    1109           1 :         };
    1110             : 
    1111           1 :         advgetopt::options_environment options_environment;
    1112           1 :         options_environment.f_project_name = "no-name-alias";
    1113           1 :         options_environment.f_options = options;
    1114           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1115           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1116           1 :         options_environment.f_environment_variable_name = nullptr;
    1117           1 :         options_environment.f_help_header = "Usage: test alias with no name specified";
    1118             : 
    1119             :         {
    1120           2 :             std::ofstream options_file;
    1121           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1122           1 :             CATCH_REQUIRE(options_file.good());
    1123             :             options_file <<
    1124             :                 "# Auto-generated\n"
    1125             : 
    1126             :                 "[foo]\n"
    1127             :                 "shortname=f\n"
    1128             :                 "default='Invalid Stuff'\n"
    1129             :                 "alias=\n"      // name missing (with an equal)
    1130             :                 "allowed=command-line\n"
    1131           1 :             ;
    1132             :         }
    1133             : 
    1134             :         char const * sub_cargv[] =
    1135             :         {
    1136             :             "tests/unittests/non_existant_alias",
    1137             :             "--verbose",
    1138             :             nullptr
    1139           1 :         };
    1140           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1141           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1142             : 
    1143           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1144             :                     , advgetopt::getopt_exception_logic
    1145             :                     , Catch::Matchers::ExceptionMessage("the default value of your alias cannot be an empty string for \"foo\"."));
    1146             :     CATCH_END_SECTION()
    1147             : 
    1148          14 :     CATCH_START_SECTION("no-name alias v2")
    1149           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
    1150           1 :         tmpdir += "/shared/advgetopt";
    1151           2 :         std::stringstream ss;
    1152           1 :         ss << "mkdir -p " << tmpdir;
    1153           1 :         if(system(ss.str().c_str()) != 0)
    1154             :         {
    1155           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1156           0 :             exit(1);
    1157             :         }
    1158           2 :         std::string const options_filename(tmpdir + "/no-name-alias-v2.ini");
    1159             : 
    1160             :         advgetopt::option const options[] =
    1161             :         {
    1162             :             advgetopt::define_option(
    1163             :                   advgetopt::Name("verbose")
    1164             :                 , advgetopt::ShortName('v')
    1165             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1166             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1167             :             ),
    1168             :             advgetopt::end_options()
    1169           1 :         };
    1170             : 
    1171           1 :         advgetopt::options_environment options_environment;
    1172           1 :         options_environment.f_project_name = "no-name-alias-v2";
    1173           1 :         options_environment.f_options = options;
    1174           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1175           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1176           1 :         options_environment.f_environment_variable_name = nullptr;
    1177           1 :         options_environment.f_help_header = "Usage: test alias with no name specified";
    1178             : 
    1179             :         {
    1180           2 :             std::ofstream options_file;
    1181           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1182           1 :             CATCH_REQUIRE(options_file.good());
    1183             :             options_file <<
    1184             :                 "# Auto-generated\n"
    1185             : 
    1186             :                 "[foo]\n"
    1187             :                 "shortname=f\n"
    1188             :                 "default='Invalid Stuff'\n"
    1189             :                 "alias\n"      // name missing (no equal)
    1190             :                 "allowed=command-line\n"
    1191           1 :             ;
    1192             :         }
    1193             : 
    1194             :         char const * sub_cargv[] =
    1195             :         {
    1196             :             "tests/unittests/non_existant_alias",
    1197             :             "--verbose",
    1198             :             nullptr
    1199           1 :         };
    1200           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1201           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1202             : 
    1203           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1204             :                     , advgetopt::getopt_exception_logic
    1205             :                     , Catch::Matchers::ExceptionMessage("the default value of your alias cannot be an empty string for \"foo\"."));
    1206             :     CATCH_END_SECTION()
    1207             : 
    1208          14 :     CATCH_START_SECTION("non-existant alias")
    1209           2 :         std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
    1210           1 :         tmpdir += "/shared/advgetopt";
    1211           2 :         std::stringstream ss;
    1212           1 :         ss << "mkdir -p " << tmpdir;
    1213           1 :         if(system(ss.str().c_str()) != 0)
    1214             :         {
    1215           0 :             std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
    1216           0 :             exit(1);
    1217             :         }
    1218           2 :         std::string const options_filename(tmpdir + "/non-existant-alias.ini");
    1219             : 
    1220             :         advgetopt::option const options[] =
    1221             :         {
    1222             :             advgetopt::define_option(
    1223             :                   advgetopt::Name("verbose")
    1224             :                 , advgetopt::ShortName('v')
    1225             :                 , advgetopt::Flags(advgetopt::standalone_all_flags<>())
    1226             :                 , advgetopt::Help("a verbose like option, select it or not.")
    1227             :             ),
    1228             :             advgetopt::end_options()
    1229           1 :         };
    1230             : 
    1231           1 :         advgetopt::options_environment options_environment;
    1232           1 :         options_environment.f_project_name = "non-existant-alias";
    1233           1 :         options_environment.f_options = options;
    1234           1 :         options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1235           1 :         options_environment.f_options_files_directory = tmpdir.c_str();
    1236           1 :         options_environment.f_environment_variable_name = nullptr;
    1237           1 :         options_environment.f_help_header = "Usage: test invalid validator specification";
    1238             : 
    1239             :         {
    1240           2 :             std::ofstream options_file;
    1241           1 :             options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
    1242           1 :             CATCH_REQUIRE(options_file.good());
    1243             :             options_file <<
    1244             :                 "# Auto-generated\n"
    1245             : 
    1246             :                 "[foo]\n"
    1247             :                 "shortname=f\n"
    1248             :                 "default='Invalid Stuff'\n"
    1249             :                 "alias=bar\n"       // option "bar" missing
    1250             :                 "allowed=command-line\n"
    1251           1 :             ;
    1252             :         }
    1253             : 
    1254             :         char const * sub_cargv[] =
    1255             :         {
    1256             :             "tests/unittests/non_existant_alias",
    1257             :             "--verbose",
    1258             :             nullptr
    1259           1 :         };
    1260           1 :         int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
    1261           1 :         char ** sub_argv = const_cast<char **>(sub_cargv);
    1262             : 
    1263           1 :         CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
    1264             :                     , advgetopt::getopt_exception_logic
    1265             :                     , Catch::Matchers::ExceptionMessage("no option named \"bar\" to satisfy the alias of \"foo\"."));
    1266             :     CATCH_END_SECTION()
    1267          13 : }
    1268             : 
    1269             : 
    1270             : 
    1271             : 
    1272             : 
    1273             : 
    1274             : 
    1275             : 
    1276             : 
    1277             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12