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-08-10 16:09:07 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.12