LCOV - code coverage report
Current view: top level - tests - catch_option_info.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 896 896 100.0 %
Date: 2022-03-01 20:39:45 Functions: 24 24 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2006-2022  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/advgetopt
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             : 
      20             : // self
      21             : //
      22             : #include    "catch_main.h"
      23             : 
      24             : 
      25             : // advgetopt lib
      26             : //
      27             : #include    <advgetopt/exception.h>
      28             : 
      29             : 
      30             : // C++ lib
      31             : //
      32             : #include    <fstream>
      33             : 
      34             : 
      35             : // last include
      36             : //
      37             : #include    <snapdev/poison.h>
      38             : 
      39             : 
      40             : 
      41             : 
      42             : 
      43           3 : CATCH_TEST_CASE("to_from_short_name", "[option_info][valid][basic][short_name]")
      44             : {
      45           2 :     CATCH_START_SECTION("Short name to string and back")
      46             :     {
      47             :         // wc == U'\0' is a special case
      48             :         //
      49           1 :         CATCH_REQUIRE(advgetopt::NO_SHORT_NAME == U'\0');
      50           1 :         CATCH_REQUIRE(advgetopt::short_name_to_string(U'\0') == std::string());
      51           1 :         CATCH_REQUIRE(advgetopt::string_to_short_name(std::string()) == U'\0');
      52             : 
      53     1112064 :         for(char32_t wc(1); wc < 0x110000; ++wc)
      54             :         {
      55     1112063 :             if(wc == 0xD800)
      56             :             {
      57           1 :                 wc = 0xE000;
      58             :             }
      59     2224126 :             std::string str(advgetopt::short_name_to_string(wc));
      60     1112063 :             CATCH_REQUIRE(advgetopt::string_to_short_name(str) == wc);
      61             : 
      62             :             // add a second character to prove that string_to_short_name()
      63             :             // only works with one character
      64             :             //
      65     1112063 :             char32_t const second_char(rand() % (0xD800 - 0x20) + 0x20);
      66     1112063 :             str += advgetopt::short_name_to_string(second_char);
      67     1112063 :             CATCH_REQUIRE(advgetopt::string_to_short_name(str) == advgetopt::NO_SHORT_NAME);
      68             :         }
      69             :     }
      70             :     CATCH_END_SECTION()
      71           1 : }
      72             : 
      73             : 
      74           3 : CATCH_TEST_CASE("parsing_string", "[environment][valid]")
      75             : {
      76           2 :     CATCH_START_SECTION("Test parsing of empty environment strings")
      77             :     {
      78           1 :         advgetopt::option const options[] =
      79             :         {
      80             :             advgetopt::define_option(
      81             :                   advgetopt::Name("empty")
      82             :                 , advgetopt::ShortName('e')
      83             :                 , advgetopt::Flags(advgetopt::command_flags<advgetopt::GETOPT_FLAG_REQUIRED>())
      84             :                 , advgetopt::Help("the empty option.")
      85             :             ),
      86             :             advgetopt::end_options()
      87             :         };
      88             : 
      89           1 :         advgetopt::options_environment environment_options;
      90           1 :         environment_options.f_project_name = "unittest";
      91           1 :         environment_options.f_options = options;
      92           1 :         environment_options.f_help_header = "Usage: test parse_string()";
      93             : 
      94           2 :         advgetopt::getopt opt(environment_options);
      95             : 
      96           1 :         CATCH_REQUIRE_THROWS_MATCHES(
      97             :                   opt.is_defined("invalid-parameter")
      98             :                 , advgetopt::getopt_initialization
      99             :                 , Catch::Matchers::ExceptionMessage(
     100             :                               "getopt_exception: function called too soon, parser is not done yet (i.e. is_defined(), get_string(), get_integer(), get_double() cannot be called until the parser is done)"));
     101             : 
     102           1 :         opt.parse_string("");
     103             : 
     104             :         // a parse without anything means that we're still uninitialized
     105             :         //
     106           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     107             :                   opt.is_defined("invalid-parameter")
     108             :                 , advgetopt::getopt_initialization
     109             :                 , Catch::Matchers::ExceptionMessage(
     110             :                               "getopt_exception: function called too soon, parser is not done yet (i.e. is_defined(), get_string(), get_integer(), get_double() cannot be called until the parser is done)"));
     111             :     }
     112             :     CATCH_END_SECTION()
     113           1 : }
     114             : 
     115             : 
     116             : 
     117             : 
     118             : 
     119           5 : CATCH_TEST_CASE("option_info_basics", "[option_info][valid][basic]")
     120             : {
     121           6 :     CATCH_START_SECTION("Simple option (verify defaults)")
     122           2 :         advgetopt::option_info verbose("verbose");
     123             : 
     124           1 :         CATCH_REQUIRE(verbose.get_name() == "verbose");
     125           1 :         CATCH_REQUIRE(verbose.get_short_name() == advgetopt::NO_SHORT_NAME);
     126           1 :         CATCH_REQUIRE_FALSE(verbose.is_default_option());
     127           1 :         CATCH_REQUIRE(verbose.get_flags() == 0);
     128             : 
     129           1 :         advgetopt::flag_t flag(1);
     130          31 :         do
     131             :         {
     132          32 :             CATCH_REQUIRE(verbose.has_flag(flag) == 0);
     133          32 :             flag <<= 1;
     134             :         }
     135          32 :         while(flag != 0);
     136             : 
     137           1 :         CATCH_REQUIRE_FALSE(verbose.has_default());
     138           1 :         CATCH_REQUIRE(verbose.get_default().empty());
     139           1 :         CATCH_REQUIRE(verbose.get_help().empty());
     140             : 
     141           1 :         CATCH_REQUIRE(verbose.get_alias_destination() == nullptr);
     142           1 :         CATCH_REQUIRE(verbose.get_multiple_separators().empty());
     143           1 :         CATCH_REQUIRE_FALSE(verbose.is_defined());
     144           1 :         CATCH_REQUIRE(verbose.size() == 0);
     145             :     CATCH_END_SECTION()
     146             : 
     147           6 :     CATCH_START_SECTION("Auto-default")
     148           2 :         advgetopt::option_info auto_default("--");
     149             : 
     150           1 :         CATCH_REQUIRE(auto_default.has_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION));
     151           1 :         CATCH_REQUIRE(auto_default.is_default_option());
     152             : 
     153           1 :         auto_default.add_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION);
     154             : 
     155           1 :         CATCH_REQUIRE(auto_default.has_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION));
     156           1 :         CATCH_REQUIRE(auto_default.is_default_option());
     157             : 
     158           1 :         auto_default.remove_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION);
     159             : 
     160           1 :         CATCH_REQUIRE_FALSE(auto_default.has_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION)); // unfortunate?
     161           1 :         CATCH_REQUIRE(auto_default.is_default_option());
     162             :     CATCH_END_SECTION()
     163             : 
     164           6 :     CATCH_START_SECTION("Explicit default")
     165           2 :         advgetopt::option_info explicit_default("filenames", 'f');
     166             : 
     167           1 :         CATCH_REQUIRE_FALSE(explicit_default.has_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION));
     168           1 :         CATCH_REQUIRE_FALSE(explicit_default.is_default_option());
     169             : 
     170           1 :         explicit_default.add_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION);
     171             : 
     172           1 :         CATCH_REQUIRE(explicit_default.has_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION));
     173           1 :         CATCH_REQUIRE(explicit_default.is_default_option());
     174             : 
     175           1 :         explicit_default.remove_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION);
     176             : 
     177           1 :         CATCH_REQUIRE_FALSE(explicit_default.has_flag(advgetopt::GETOPT_FLAG_DEFAULT_OPTION));
     178           1 :         CATCH_REQUIRE_FALSE(explicit_default.is_default_option());
     179             :     CATCH_END_SECTION()
     180           3 : }
     181             : 
     182             : 
     183             : 
     184           3 : CATCH_TEST_CASE("option_info_flags", "[option_info][valid][flags]")
     185             : {
     186           2 :     CATCH_START_SECTION("Check flags")
     187           2 :         advgetopt::option_info flags("flags", 'f');
     188             : 
     189           1 :         advgetopt::flag_t flag(1);
     190          31 :         do
     191             :         {
     192          32 :             CATCH_REQUIRE(flags.get_flags() == 0);
     193             : 
     194          32 :             advgetopt::flag_t clear(1);
     195         992 :             do
     196             :             {
     197        1024 :                 CATCH_REQUIRE_FALSE(flags.has_flag(clear));
     198        1024 :                 clear <<= 1;
     199             :             }
     200        1024 :             while(clear != 0);
     201             : 
     202          32 :             flags.add_flag(flag);
     203          32 :             CATCH_REQUIRE(flags.has_flag(flag));
     204          32 :             CATCH_REQUIRE(flags.get_flags() == flag);
     205             : 
     206          32 :             advgetopt::flag_t set(1);
     207         992 :             do
     208             :             {
     209        1024 :                 if(set == flag)
     210             :                 {
     211          32 :                     CATCH_REQUIRE(flags.has_flag(set));
     212             :                 }
     213             :                 else
     214             :                 {
     215         992 :                     CATCH_REQUIRE_FALSE(flags.has_flag(set));
     216             :                 }
     217        1024 :                 set <<= 1;
     218             :             }
     219        1024 :             while(set != 0);
     220             : 
     221          32 :             flags.remove_flag(flag);
     222          32 :             CATCH_REQUIRE(flags.get_flags() == 0);
     223             : 
     224          32 :             clear = 1;
     225         992 :             do
     226             :             {
     227        1024 :                 CATCH_REQUIRE_FALSE(flags.has_flag(clear));
     228        1024 :                 clear <<= 1;
     229             :             }
     230        1024 :             while(clear != 0);
     231             : 
     232          32 :             flag <<= 1;
     233             :         }
     234          32 :         while(flag != 0);
     235             : 
     236           1 :         flag = 1;
     237          31 :         do
     238             :         {
     239          32 :             CATCH_REQUIRE(flags.get_flags() == 0);
     240             : 
     241          32 :             advgetopt::flag_t clear(1);
     242         992 :             do
     243             :             {
     244        1024 :                 CATCH_REQUIRE_FALSE(flags.has_flag(clear));
     245        1024 :                 clear <<= 1;
     246             :             }
     247        1024 :             while(clear != 0);
     248             : 
     249          32 :             flags.set_flags(flag);
     250          32 :             CATCH_REQUIRE(flags.has_flag(flag));
     251          32 :             CATCH_REQUIRE(flags.get_flags() == flag);
     252             : 
     253          32 :             advgetopt::flag_t set(1);
     254         992 :             do
     255             :             {
     256        1024 :                 if(set == flag)
     257             :                 {
     258          32 :                     CATCH_REQUIRE(flags.has_flag(set));
     259             :                 }
     260             :                 else
     261             :                 {
     262         992 :                     CATCH_REQUIRE_FALSE(flags.has_flag(set));
     263             :                 }
     264        1024 :                 set <<= 1;
     265             :             }
     266        1024 :             while(set != 0);
     267             : 
     268          32 :             flags.set_flags(0);
     269          32 :             CATCH_REQUIRE(flags.get_flags() == 0);
     270             : 
     271          32 :             clear = 1;
     272         992 :             do
     273             :             {
     274        1024 :                 CATCH_REQUIRE_FALSE(flags.has_flag(clear));
     275        1024 :                 clear <<= 1;
     276             :             }
     277        1024 :             while(clear != 0);
     278             : 
     279          32 :             flag <<= 1;
     280             :         }
     281          32 :         while(flag != 0);
     282             :     CATCH_END_SECTION()
     283           1 : }
     284             : 
     285             : 
     286             : 
     287           3 : CATCH_TEST_CASE("option_info_default", "[option_info][valid][default]")
     288             : {
     289           2 :     CATCH_START_SECTION("Set/remove default")
     290           2 :         advgetopt::option_info with_default("with_default", 'w');
     291             : 
     292           1 :         CATCH_REQUIRE_FALSE(with_default.has_default());
     293           1 :         CATCH_REQUIRE_FALSE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     294           1 :         CATCH_REQUIRE(with_default.get_default().empty());
     295             : 
     296           1 :         with_default.set_default("working");
     297           1 :         CATCH_REQUIRE(with_default.has_default());
     298           1 :         CATCH_REQUIRE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     299           1 :         CATCH_REQUIRE(with_default.get_default() == "working");
     300             : 
     301           1 :         with_default.remove_default();
     302           1 :         CATCH_REQUIRE_FALSE(with_default.has_default());
     303           1 :         CATCH_REQUIRE_FALSE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     304           1 :         CATCH_REQUIRE(with_default.get_default().empty());
     305             : 
     306           2 :         std::string const default_value("other");
     307           1 :         with_default.set_default(default_value);
     308           1 :         CATCH_REQUIRE(with_default.has_default());
     309           1 :         CATCH_REQUIRE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     310           1 :         CATCH_REQUIRE(with_default.get_default() == default_value);
     311             : 
     312           1 :         with_default.remove_default();
     313           1 :         CATCH_REQUIRE_FALSE(with_default.has_default());
     314           1 :         CATCH_REQUIRE_FALSE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     315           1 :         CATCH_REQUIRE(with_default.get_default().empty());
     316             : 
     317           2 :         std::string const empty_default;
     318           1 :         with_default.set_default(empty_default);
     319           1 :         CATCH_REQUIRE(with_default.has_default());
     320           1 :         CATCH_REQUIRE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     321           1 :         CATCH_REQUIRE(with_default.get_default().empty());
     322             : 
     323           1 :         with_default.remove_default();
     324           1 :         CATCH_REQUIRE_FALSE(with_default.has_default());
     325           1 :         CATCH_REQUIRE_FALSE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     326           1 :         CATCH_REQUIRE(with_default.get_default().empty());
     327             : 
     328           1 :         with_default.set_default(nullptr); // no effects
     329           1 :         CATCH_REQUIRE_FALSE(with_default.has_default());
     330           1 :         CATCH_REQUIRE_FALSE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     331           1 :         CATCH_REQUIRE(with_default.get_default().empty());
     332             : 
     333           2 :         std::string const null_value("null works too");
     334           1 :         with_default.set_default(null_value);
     335           1 :         CATCH_REQUIRE(with_default.has_default());
     336           1 :         CATCH_REQUIRE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     337           1 :         CATCH_REQUIRE(with_default.get_default() == null_value);
     338             : 
     339           1 :         with_default.set_default(nullptr); // no effects
     340           1 :         CATCH_REQUIRE(with_default.has_default());
     341           1 :         CATCH_REQUIRE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     342           1 :         CATCH_REQUIRE(with_default.get_default() == null_value);
     343             : 
     344           1 :         with_default.remove_default();
     345           1 :         CATCH_REQUIRE_FALSE(with_default.has_default());
     346           1 :         CATCH_REQUIRE_FALSE(with_default.has_flag(advgetopt::GETOPT_FLAG_HAS_DEFAULT));
     347           1 :         CATCH_REQUIRE(with_default.get_default().empty());
     348             :     CATCH_END_SECTION()
     349           1 : }
     350             : 
     351             : 
     352             : 
     353           3 : CATCH_TEST_CASE("option_info_help", "[option_info][valid][help]")
     354             : {
     355           2 :     CATCH_START_SECTION("Check help")
     356           2 :         advgetopt::option_info help("help", 'h');
     357             : 
     358           1 :         CATCH_REQUIRE(help.get_help().empty());
     359             : 
     360           1 :         help.set_help("help me");
     361           1 :         CATCH_REQUIRE(help.get_help() == "help me");
     362             : 
     363           2 :         std::string const msg("help msg");
     364           1 :         help.set_help(msg);
     365           1 :         CATCH_REQUIRE(help.get_help() == msg);
     366             : 
     367           1 :         help.set_help(nullptr);
     368           1 :         CATCH_REQUIRE(help.get_help() == msg);
     369             : 
     370           1 :         help.set_help("");
     371           1 :         CATCH_REQUIRE(help.get_help().empty());
     372             :     CATCH_END_SECTION()
     373           1 : }
     374             : 
     375             : 
     376             : 
     377           6 : CATCH_TEST_CASE("option_info_validator", "[option_info][valid][validator]")
     378             : {
     379           8 :     CATCH_START_SECTION("Check validator (one value)")
     380             :     {
     381           2 :         advgetopt::option_info auto_validate("validator", 'C');
     382           1 :         auto_validate.set_flags(advgetopt::GETOPT_FLAG_DYNAMIC_CONFIGURATION);
     383             : 
     384           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     385             : 
     386           1 :         auto_validate.set_value(0, "51");
     387           1 :         CATCH_REQUIRE(auto_validate.size() == 1);
     388           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "51");
     389           1 :         CATCH_REQUIRE(auto_validate.get_long(0) == 51);
     390           1 :         CATCH_REQUIRE(auto_validate.source() == advgetopt::option_source_t::SOURCE_DIRECT);
     391             : 
     392           1 :         auto_validate.set_validator(nullptr);
     393           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     394             : 
     395           2 :         advgetopt::validator::pointer_t integer_validator(advgetopt::validator::create("integer", {"1","2","5","6","8"}));
     396           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"51\" given to parameter --validator is not considered valid.");
     397           1 :         auto_validate.set_validator(integer_validator);
     398           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     399           1 :         CATCH_REQUIRE(auto_validate.get_validator() == integer_validator);
     400             : 
     401           1 :         auto_validate.set_value(0, "6", advgetopt::option_source_t::SOURCE_DYNAMIC);
     402           1 :         CATCH_REQUIRE(auto_validate.source() == advgetopt::option_source_t::SOURCE_DYNAMIC);
     403             : 
     404           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"3\" given to parameter --validator is not considered valid.");
     405           1 :         auto_validate.set_value(0, "3", advgetopt::option_source_t::SOURCE_CONFIGURATION);
     406           1 :         CATCH_REQUIRE(auto_validate.source() == advgetopt::option_source_t::SOURCE_UNDEFINED);    // it doesn't take... it gets cleared though
     407           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     408             : 
     409           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"11\" given to parameter --validator is not considered valid.");
     410           1 :         auto_validate.set_value(0, "11", advgetopt::option_source_t::SOURCE_ENVIRONMENT_VARIABLE);
     411           1 :         CATCH_REQUIRE(auto_validate.source() == advgetopt::option_source_t::SOURCE_UNDEFINED);    // it doesn't take... it gets cleared though
     412           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     413             :     }
     414             :     CATCH_END_SECTION()
     415             : 
     416           8 :     CATCH_START_SECTION("Check validator (multiple values)")
     417             :     {
     418           2 :         advgetopt::option_info auto_validate("validator", 'C');
     419             : 
     420           1 :         auto_validate.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
     421             : 
     422           2 :         advgetopt::string_list_t list{","};
     423           1 :         auto_validate.set_multiple_separators(list);
     424             : 
     425           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     426             : 
     427           1 :         auto_validate.set_value(0, "-15", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     428           1 :         CATCH_REQUIRE(auto_validate.size() == 1);
     429           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "-15");
     430           1 :         CATCH_REQUIRE(auto_validate.get_long(0) == -15);
     431             : 
     432           1 :         auto_validate.set_validator(nullptr);
     433           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     434             : 
     435           2 :         advgetopt::validator::pointer_t integer_validator(advgetopt::validator::create("integer", {"-1","2","5","6","18"}));
     436           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"-15\" given to parameter --validator is not considered valid.");
     437           1 :         auto_validate.set_validator(integer_validator);
     438           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     439           1 :         CATCH_REQUIRE(auto_validate.get_validator() == integer_validator);
     440             : 
     441           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"3\" given to parameter --validator is not considered valid.");
     442           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"11\" given to parameter --validator is not considered valid.");
     443           1 :         CATCH_REQUIRE_FALSE(auto_validate.set_multiple_values("6,3,18,11", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     444           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     445           1 :         CATCH_REQUIRE(auto_validate.size() == 2);
     446           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "6");
     447           1 :         CATCH_REQUIRE(auto_validate.get_long(0) == 6);
     448           1 :         CATCH_REQUIRE(auto_validate.get_value(1) == "18");
     449           1 :         CATCH_REQUIRE(auto_validate.get_long(1) == 18);
     450             : 
     451           1 :         auto_validate.set_validator(nullptr);
     452           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     453             : 
     454           1 :         CATCH_REQUIRE(auto_validate.set_multiple_values("6,3,18,11", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     455           1 :         CATCH_REQUIRE(auto_validate.size() == 4);
     456           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "6");
     457           1 :         CATCH_REQUIRE(auto_validate.get_long(0) == 6);
     458           1 :         CATCH_REQUIRE(auto_validate.get_value(1) == "3");
     459           1 :         CATCH_REQUIRE(auto_validate.get_long(1) == 3);
     460           1 :         CATCH_REQUIRE(auto_validate.get_value(2) == "18");
     461           1 :         CATCH_REQUIRE(auto_validate.get_long(2) == 18);
     462           1 :         CATCH_REQUIRE(auto_validate.get_value(3) == "11");
     463           1 :         CATCH_REQUIRE(auto_validate.get_long(3) == 11);
     464             :     }
     465             :     CATCH_END_SECTION()
     466             : 
     467           8 :     CATCH_START_SECTION("Check integer validator from string (multiple values)")
     468             :     {
     469           2 :         advgetopt::option_info auto_validate("validator", 'C');
     470             : 
     471           1 :         auto_validate.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
     472             : 
     473           2 :         advgetopt::string_list_t list{","};
     474           1 :         auto_validate.set_multiple_separators(list);
     475             : 
     476           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     477             : 
     478           1 :         auto_validate.set_value(0, "35", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     479           1 :         CATCH_REQUIRE(auto_validate.size() == 1);
     480           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "35");
     481           1 :         CATCH_REQUIRE(auto_validate.get_long(0) == 35);
     482             : 
     483           1 :         auto_validate.set_validator(nullptr);
     484           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     485             : 
     486           1 :         auto_validate.set_validator(std::string());
     487           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     488             : 
     489           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"35\" given to parameter --validator is not considered valid.");
     490           1 :         auto_validate.set_validator("integer(-1,2,5,6,18)");
     491           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     492           1 :         CATCH_REQUIRE(auto_validate.get_validator() != nullptr);
     493           1 :         CATCH_REQUIRE(auto_validate.get_validator()->name() == "integer");
     494             : 
     495           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"3\" given to parameter --validator is not considered valid.");
     496           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"11\" given to parameter --validator is not considered valid.");
     497           1 :         CATCH_REQUIRE_FALSE(auto_validate.set_multiple_values("6,3,18,11", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     498           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     499           1 :         CATCH_REQUIRE(auto_validate.size() == 2);
     500           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "6");
     501           1 :         CATCH_REQUIRE(auto_validate.get_long(0) == 6);
     502           1 :         CATCH_REQUIRE(auto_validate.get_value(1) == "18");
     503           1 :         CATCH_REQUIRE(auto_validate.get_long(1) == 18);
     504             : 
     505           1 :         auto_validate.set_validator(std::string());
     506           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     507             : 
     508           1 :         CATCH_REQUIRE(auto_validate.set_multiple_values("6,3,18,11", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     509           1 :         CATCH_REQUIRE(auto_validate.size() == 4);
     510           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "6");
     511           1 :         CATCH_REQUIRE(auto_validate.get_long(0) == 6);
     512           1 :         CATCH_REQUIRE(auto_validate.get_value(1) == "3");
     513           1 :         CATCH_REQUIRE(auto_validate.get_long(1) == 3);
     514           1 :         CATCH_REQUIRE(auto_validate.get_value(2) == "18");
     515           1 :         CATCH_REQUIRE(auto_validate.get_long(2) == 18);
     516           1 :         CATCH_REQUIRE(auto_validate.get_value(3) == "11");
     517           1 :         CATCH_REQUIRE(auto_validate.get_long(3) == 11);
     518             :     }
     519             :     CATCH_END_SECTION()
     520             : 
     521           8 :     CATCH_START_SECTION("Check regex validator from string (multiple values)")
     522             :     {
     523           2 :         advgetopt::option_info auto_validate("validator", 'C');
     524             : 
     525           1 :         auto_validate.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
     526             : 
     527           2 :         advgetopt::string_list_t list{","};
     528           1 :         auto_validate.set_multiple_separators(list);
     529             : 
     530           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     531             : 
     532           1 :         auto_validate.set_value(0, "abc", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     533           1 :         CATCH_REQUIRE(auto_validate.size() == 1);
     534           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "abc");
     535             : 
     536           1 :         auto_validate.set_validator(nullptr);
     537           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     538             : 
     539           1 :         auto_validate.set_validator(std::string());
     540           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     541             : 
     542           1 :         auto_validate.set_validator("/^[a-z]+$/");
     543           1 :         CATCH_REQUIRE(auto_validate.get_validator() != nullptr);
     544           1 :         CATCH_REQUIRE(auto_validate.get_validator()->name() == "regex");
     545             : 
     546           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"33\" given to parameter --validator is not considered valid.");
     547           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"45\" given to parameter --validator is not considered valid.");
     548           1 :         CATCH_REQUIRE_FALSE(auto_validate.set_multiple_values("abc,qqq,33,zac,pop,45", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     549           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
     550           1 :         CATCH_REQUIRE(auto_validate.size() == 4);
     551           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "abc");
     552           1 :         CATCH_REQUIRE(auto_validate.get_value(1) == "qqq");
     553           1 :         CATCH_REQUIRE(auto_validate.get_value(2) == "zac");
     554           1 :         CATCH_REQUIRE(auto_validate.get_value(3) == "pop");
     555             : 
     556           1 :         auto_validate.set_validator(std::string());
     557           1 :         CATCH_REQUIRE(auto_validate.get_validator() == nullptr);
     558             : 
     559           1 :         CATCH_REQUIRE(auto_validate.set_multiple_values("abc,-56,zoc", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     560           1 :         CATCH_REQUIRE(auto_validate.size() == 3);
     561           1 :         CATCH_REQUIRE(auto_validate.get_value(0) == "abc");
     562           1 :         CATCH_REQUIRE(auto_validate.get_value(1) == "-56");
     563           1 :         CATCH_REQUIRE(auto_validate.get_value(2) == "zoc");
     564             :     }
     565             :     CATCH_END_SECTION()
     566           4 : }
     567             : 
     568             : 
     569             : 
     570             : 
     571           3 : CATCH_TEST_CASE("option_info_alias", "[option_info][valid][alias]")
     572             : {
     573           2 :     CATCH_START_SECTION("Check alias")
     574           2 :         advgetopt::option_info::pointer_t option(std::make_shared<advgetopt::option_info>("option", 'o'));
     575           2 :         advgetopt::option_info alias("alias", 'a');
     576             : 
     577           1 :         CATCH_REQUIRE(alias.get_alias_destination() == nullptr);
     578             : 
     579           1 :         alias.set_alias_destination(option);
     580             : 
     581           1 :         CATCH_REQUIRE(alias.get_alias_destination() == option);
     582             :     CATCH_END_SECTION()
     583           1 : }
     584             : 
     585             : 
     586             : 
     587           3 : CATCH_TEST_CASE("option_info_multiple_separators", "[option_info][valid][separators][multiple]")
     588             : {
     589           2 :     CATCH_START_SECTION("Check multiple separators")
     590           2 :         advgetopt::option_info separators("names", 'n');
     591             : 
     592           1 :         separators.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
     593             : 
     594           1 :         CATCH_REQUIRE(separators.get_multiple_separators().empty());
     595             : 
     596           1 :         separators.set_multiple_separators(nullptr);
     597           1 :         CATCH_REQUIRE(separators.get_multiple_separators().empty());
     598             : 
     599           1 :         CATCH_REQUIRE(separators.set_multiple_values("n1,n2;n3 n4 ^ n5", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     600           1 :         CATCH_REQUIRE(separators.size() == 1);
     601           1 :         CATCH_REQUIRE(separators.get_value(0) == "n1,n2;n3 n4 ^ n5");
     602             : 
     603           2 :         advgetopt::string_list_t empty_list;
     604           1 :         separators.set_multiple_separators(empty_list);
     605           1 :         CATCH_REQUIRE(separators.get_multiple_separators().empty());
     606             : 
     607           1 :         CATCH_REQUIRE(separators.set_multiple_values("n1,n2;n3 n4 ^ n5", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     608           1 :         CATCH_REQUIRE(separators.size() == 1);
     609           1 :         CATCH_REQUIRE(separators.get_value(0) == "n1,n2;n3 n4 ^ n5");
     610             : 
     611           1 :         char const * const empty_separator_list[]{
     612             :             nullptr
     613             :         };
     614           1 :         separators.set_multiple_separators(empty_separator_list);
     615           1 :         CATCH_REQUIRE(separators.get_multiple_separators().empty());
     616             : 
     617           1 :         CATCH_REQUIRE(separators.set_multiple_values("n1,n2;n3 n4 ^ n5", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     618           1 :         CATCH_REQUIRE(separators.size() == 1);
     619           1 :         CATCH_REQUIRE(separators.get_value(0) == "n1,n2;n3 n4 ^ n5");
     620             : 
     621           1 :         char const * const separator_list[]{
     622             :             ",",
     623             :             ";",
     624             :             " ",
     625             :             "^",
     626             :             nullptr
     627             :         };
     628           1 :         separators.set_multiple_separators(separator_list);
     629           1 :         CATCH_REQUIRE(separators.get_multiple_separators().size() == 4);
     630             : 
     631           1 :         CATCH_REQUIRE(separators.set_multiple_values("n1,n2;n3 n4 ^ n5", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     632           1 :         CATCH_REQUIRE(separators.size() == 5);
     633           1 :         CATCH_REQUIRE(separators.get_value(0) == "n1");
     634           1 :         CATCH_REQUIRE(separators.get_value(1) == "n2");
     635           1 :         CATCH_REQUIRE(separators.get_value(2) == "n3");
     636           1 :         CATCH_REQUIRE(separators.get_value(3) == "n4");
     637           1 :         CATCH_REQUIRE(separators.get_value(4) == "n5");
     638             : 
     639           1 :         separators.set_multiple_separators(empty_separator_list);
     640           1 :         CATCH_REQUIRE(separators.get_multiple_separators().empty());
     641             : 
     642           1 :         CATCH_REQUIRE(separators.set_multiple_values("n1,n2;n3 n4 ^ n5", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     643           1 :         CATCH_REQUIRE(separators.size() == 1);
     644           1 :         CATCH_REQUIRE(separators.get_value(0) == "n1,n2;n3 n4 ^ n5");
     645             : 
     646           1 :         advgetopt::string_list_t list{
     647             :             ",",
     648             :             ";",
     649             :             " ",
     650             :             "^",
     651           2 :         };
     652           1 :         separators.set_multiple_separators(list);
     653           1 :         CATCH_REQUIRE(separators.get_multiple_separators().size() == 4);
     654             : 
     655           1 :         CATCH_REQUIRE(separators.set_multiple_values("n1,n2;n3 n4 ^ n5", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     656           1 :         CATCH_REQUIRE(separators.size() == 5);
     657           1 :         CATCH_REQUIRE(separators.get_value(0) == "n1");
     658           1 :         CATCH_REQUIRE(separators.get_value(1) == "n2");
     659           1 :         CATCH_REQUIRE(separators.get_value(2) == "n3");
     660           1 :         CATCH_REQUIRE(separators.get_value(3) == "n4");
     661           1 :         CATCH_REQUIRE(separators.get_value(4) == "n5");
     662             : 
     663           1 :         separators.set_multiple_separators(empty_list);
     664           1 :         CATCH_REQUIRE(separators.get_multiple_separators().empty());
     665             : 
     666           1 :         CATCH_REQUIRE(separators.set_multiple_values("n1,n2;n3 n4 ^ n5", advgetopt::option_source_t::SOURCE_COMMAND_LINE));
     667           1 :         CATCH_REQUIRE(separators.size() == 1);
     668           1 :         CATCH_REQUIRE(separators.get_value(0) == "n1,n2;n3 n4 ^ n5");
     669             :     CATCH_END_SECTION()
     670           1 : }
     671             : 
     672             : 
     673             : 
     674           6 : CATCH_TEST_CASE("option_info_add_value", "[option_info][valid][add][multiple]")
     675             : {
     676           8 :     CATCH_START_SECTION("Add value, verify lock (add/remove flag explicitly)")
     677           2 :         advgetopt::option_info one_value("names", 'n');
     678             : 
     679           1 :         CATCH_REQUIRE(one_value.size() == 0);
     680             : 
     681           1 :         one_value.add_value("value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     682           1 :         CATCH_REQUIRE(one_value.size() == 1);
     683           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value one");
     684             : 
     685           1 :         one_value.add_value("value two", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     686           1 :         CATCH_REQUIRE(one_value.size() == 1);
     687           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value two");
     688             : 
     689           1 :         one_value.add_flag(advgetopt::GETOPT_FLAG_LOCK);
     690             : 
     691           1 :         one_value.add_value("value three", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     692           1 :         CATCH_REQUIRE(one_value.size() == 1);
     693           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value two");
     694             : 
     695           1 :         one_value.remove_flag(advgetopt::GETOPT_FLAG_LOCK);
     696             : 
     697           1 :         one_value.add_value("value four", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     698           1 :         CATCH_REQUIRE(one_value.size() == 1);
     699           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value four");
     700             : 
     701           1 :         one_value.reset();
     702           1 :         CATCH_REQUIRE(one_value.size() == 0);
     703             : 
     704             :         // to verify that the f_integer was reset we kind of very much
     705             :         // have to re-add a value
     706             :         //
     707           1 :         one_value.set_value(0, "value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     708           1 :         CATCH_REQUIRE(one_value.size() == 1);
     709           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value one");
     710             :     CATCH_END_SECTION()
     711             : 
     712           8 :     CATCH_START_SECTION("Add value, verify integer")
     713           2 :         advgetopt::option_info one_value("names", 'n');
     714             : 
     715           1 :         CATCH_REQUIRE(one_value.size() == 0);
     716             : 
     717           1 :         one_value.add_value("123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     718           1 :         CATCH_REQUIRE(one_value.size() == 1);
     719           1 :         CATCH_REQUIRE(one_value.get_value(0) == "123");
     720           1 :         CATCH_REQUIRE(one_value.get_long(0) == 123);
     721             : 
     722           1 :         one_value.add_value("456", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     723           1 :         CATCH_REQUIRE(one_value.size() == 1);
     724           1 :         CATCH_REQUIRE(one_value.get_value(0) == "456");
     725           1 :         CATCH_REQUIRE(one_value.get_long(0) == 456);
     726             : 
     727           1 :         one_value.add_flag(advgetopt::GETOPT_FLAG_LOCK);
     728             : 
     729           1 :         one_value.add_value("789", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     730           1 :         CATCH_REQUIRE(one_value.size() == 1);
     731           1 :         CATCH_REQUIRE(one_value.get_value(0) == "456");
     732           1 :         CATCH_REQUIRE(one_value.get_long(0) == 456);
     733             : 
     734           1 :         one_value.remove_flag(advgetopt::GETOPT_FLAG_LOCK);
     735             : 
     736           1 :         one_value.add_value("505", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     737           1 :         CATCH_REQUIRE(one_value.size() == 1);
     738           1 :         CATCH_REQUIRE(one_value.get_value(0) == "505");
     739           1 :         CATCH_REQUIRE(one_value.get_long(0) == 505);
     740             : 
     741           1 :         one_value.reset();
     742           1 :         CATCH_REQUIRE(one_value.size() == 0);
     743             : 
     744             :         // to verify that the f_integer was reset we kind of very much
     745             :         // have to re-add a value
     746             :         //
     747           1 :         one_value.set_value(0, "123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     748           1 :         CATCH_REQUIRE(one_value.size() == 1);
     749           1 :         CATCH_REQUIRE(one_value.get_value(0) == "123");
     750           1 :         CATCH_REQUIRE(one_value.get_long(0) == 123);
     751             :     CATCH_END_SECTION()
     752             : 
     753           8 :     CATCH_START_SECTION("Add value, verify multiple strings")
     754           2 :         advgetopt::option_info multi_value("names", 'n');
     755             : 
     756           1 :         CATCH_REQUIRE(multi_value.size() == 0);
     757             : 
     758           1 :         multi_value.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
     759             : 
     760           1 :         multi_value.add_value("value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     761           1 :         CATCH_REQUIRE(multi_value.size() == 1);
     762           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     763             : 
     764           1 :         multi_value.add_value("value two", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     765           1 :         CATCH_REQUIRE(multi_value.size() == 2);
     766           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     767           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "value two");
     768             : 
     769           1 :         multi_value.add_flag(advgetopt::GETOPT_FLAG_LOCK);
     770             : 
     771           1 :         multi_value.add_value("value three", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     772           1 :         CATCH_REQUIRE(multi_value.size() == 2);
     773           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     774           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "value two");
     775             : 
     776           1 :         multi_value.remove_flag(advgetopt::GETOPT_FLAG_LOCK);
     777             : 
     778           1 :         multi_value.add_value("value four", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     779           1 :         CATCH_REQUIRE(multi_value.size() == 3);
     780           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     781           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "value two");
     782           1 :         CATCH_REQUIRE(multi_value.get_value(2) == "value four");
     783             : 
     784           1 :         multi_value.reset();
     785           1 :         CATCH_REQUIRE(multi_value.size() == 0);
     786             : 
     787             :         // to verify that the f_integer was reset we kind of very much
     788             :         // have to re-add a value
     789             :         //
     790           1 :         multi_value.set_value(0, "value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     791           1 :         CATCH_REQUIRE(multi_value.size() == 1);
     792           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     793             :     CATCH_END_SECTION()
     794             : 
     795           8 :     CATCH_START_SECTION("Add value, verify multiple integers")
     796           2 :         advgetopt::option_info multi_value("names", 'n');
     797             : 
     798           1 :         CATCH_REQUIRE(multi_value.size() == 0);
     799             : 
     800           1 :         multi_value.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
     801             : 
     802           1 :         multi_value.add_value("123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     803           1 :         CATCH_REQUIRE(multi_value.size() == 1);
     804           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
     805           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
     806             : 
     807           1 :         multi_value.add_value("456", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     808           1 :         CATCH_REQUIRE(multi_value.size() == 2);
     809           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
     810           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
     811           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "456");
     812           1 :         CATCH_REQUIRE(multi_value.get_long(1) == 456);
     813             : 
     814           1 :         multi_value.add_flag(advgetopt::GETOPT_FLAG_LOCK);
     815             : 
     816           1 :         multi_value.add_value("789", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     817           1 :         CATCH_REQUIRE(multi_value.size() == 2);
     818           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
     819           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
     820           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "456");
     821           1 :         CATCH_REQUIRE(multi_value.get_long(1) == 456);
     822             : 
     823           1 :         multi_value.remove_flag(advgetopt::GETOPT_FLAG_LOCK);
     824             : 
     825           1 :         multi_value.add_value("505", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     826           1 :         CATCH_REQUIRE(multi_value.size() == 3);
     827           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
     828           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
     829           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "456");
     830           1 :         CATCH_REQUIRE(multi_value.get_long(1) == 456);
     831           1 :         CATCH_REQUIRE(multi_value.get_value(2) == "505");
     832           1 :         CATCH_REQUIRE(multi_value.get_long(2) == 505);
     833             : 
     834           1 :         multi_value.reset();
     835           1 :         CATCH_REQUIRE(multi_value.size() == 0);
     836             : 
     837             :         // to verify that the f_integer was reset we kind of very much
     838             :         // have to re-add a value
     839             :         //
     840           1 :         multi_value.set_value(0, "123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     841           1 :         CATCH_REQUIRE(multi_value.size() == 1);
     842           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
     843           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
     844             :     CATCH_END_SECTION()
     845           4 : }
     846             : 
     847             : 
     848             : 
     849           6 : CATCH_TEST_CASE("option_info_set_value", "[option_info][valid][set][multiple]")
     850             : {
     851           8 :     CATCH_START_SECTION("Set value, verify lock (use lock()/unlock() functions)")
     852           2 :         advgetopt::option_info one_value("names", 'n');
     853             : 
     854           1 :         CATCH_REQUIRE(one_value.size() == 0);
     855             : 
     856           1 :         one_value.set_value(0, "value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     857           1 :         CATCH_REQUIRE(one_value.size() == 1);
     858           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value one");
     859             : 
     860           1 :         one_value.set_value(0, "value two", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     861           1 :         CATCH_REQUIRE(one_value.size() == 1);
     862           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value two");
     863             : 
     864           1 :         one_value.lock();
     865             : 
     866           1 :         one_value.set_value(0, "value three", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     867           1 :         CATCH_REQUIRE(one_value.size() == 1);
     868           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value two");
     869             : 
     870           1 :         one_value.unlock();
     871             : 
     872           1 :         one_value.set_value(0, "value four", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     873           1 :         CATCH_REQUIRE(one_value.size() == 1);
     874           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value four");
     875             : 
     876           1 :         one_value.reset();
     877           1 :         CATCH_REQUIRE(one_value.size() == 0);
     878             : 
     879             :         // to verify that the f_integer was reset we kind of very much
     880             :         // have to re-add a value
     881             :         //
     882           1 :         one_value.set_value(0, "value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     883           1 :         CATCH_REQUIRE(one_value.size() == 1);
     884           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value one");
     885             :     CATCH_END_SECTION()
     886             : 
     887           8 :     CATCH_START_SECTION("Set value, verify integer")
     888           2 :         advgetopt::option_info one_value("names", 'n');
     889             : 
     890           1 :         CATCH_REQUIRE(one_value.size() == 0);
     891             : 
     892           1 :         one_value.set_value(0, "123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     893           1 :         CATCH_REQUIRE(one_value.size() == 1);
     894           1 :         CATCH_REQUIRE(one_value.get_value(0) == "123");
     895           1 :         CATCH_REQUIRE(one_value.get_long(0) == 123);
     896             : 
     897           1 :         one_value.set_value(0, "456", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     898           1 :         CATCH_REQUIRE(one_value.size() == 1);
     899           1 :         CATCH_REQUIRE(one_value.get_value(0) == "456");
     900           1 :         CATCH_REQUIRE(one_value.get_long(0) == 456);
     901             : 
     902           1 :         one_value.lock();
     903             : 
     904           1 :         one_value.set_value(0, "789", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     905           1 :         CATCH_REQUIRE(one_value.size() == 1);
     906           1 :         CATCH_REQUIRE(one_value.get_value(0) == "456");
     907           1 :         CATCH_REQUIRE(one_value.get_long(0) == 456);
     908             : 
     909           1 :         one_value.unlock();
     910             : 
     911           1 :         one_value.set_value(0, "505", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     912           1 :         CATCH_REQUIRE(one_value.size() == 1);
     913           1 :         CATCH_REQUIRE(one_value.get_value(0) == "505");
     914           1 :         CATCH_REQUIRE(one_value.get_long(0) == 505);
     915             : 
     916           1 :         one_value.reset();
     917           1 :         CATCH_REQUIRE(one_value.size() == 0);
     918             : 
     919             :         // to verify that the f_integer was reset we kind of very much
     920             :         // have to re-add a value
     921             :         //
     922           1 :         one_value.set_value(0, "123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     923           1 :         CATCH_REQUIRE(one_value.size() == 1);
     924           1 :         CATCH_REQUIRE(one_value.get_value(0) == "123");
     925           1 :         CATCH_REQUIRE(one_value.get_long(0) == 123);
     926             :     CATCH_END_SECTION()
     927             : 
     928           8 :     CATCH_START_SECTION("Set value, verify multiple strings (with MULTIPLE & lock(false))")
     929           2 :         advgetopt::option_info multi_value("names", 'n');
     930             : 
     931           1 :         multi_value.lock(false);
     932             : 
     933           1 :         CATCH_REQUIRE(multi_value.size() == 0);
     934             : 
     935           1 :         multi_value.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
     936             : 
     937           1 :         multi_value.set_value(0, "value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     938           1 :         CATCH_REQUIRE(multi_value.size() == 1);
     939           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     940             : 
     941           1 :         multi_value.set_value(1, "value two", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     942           1 :         CATCH_REQUIRE(multi_value.size() == 2);
     943           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     944           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "value two");
     945             : 
     946           1 :         multi_value.lock(false);
     947             : 
     948           1 :         multi_value.set_value(2, "value three", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     949           1 :         CATCH_REQUIRE(multi_value.size() == 2);
     950           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     951           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "value two");
     952             : 
     953           1 :         multi_value.unlock();
     954             : 
     955           1 :         multi_value.set_value(2, "value four", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     956           1 :         CATCH_REQUIRE(multi_value.size() == 3);
     957           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     958           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "value two");
     959           1 :         CATCH_REQUIRE(multi_value.get_value(2) == "value four");
     960             : 
     961           1 :         multi_value.reset();
     962           1 :         CATCH_REQUIRE(multi_value.size() == 0);
     963             : 
     964             :         // to verify that the f_integer was reset we kind of very much
     965             :         // have to re-add a value
     966             :         //
     967           1 :         multi_value.set_value(0, "value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     968           1 :         CATCH_REQUIRE(multi_value.size() == 1);
     969           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
     970             :     CATCH_END_SECTION()
     971             : 
     972           8 :     CATCH_START_SECTION("Set value, verify multiple integers (with MULTIPLE & lock(false))")
     973           2 :         advgetopt::option_info multi_value("names", 'n');
     974             : 
     975           1 :         CATCH_REQUIRE(multi_value.size() == 0);
     976             : 
     977           1 :         multi_value.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
     978             : 
     979           1 :         multi_value.lock(false);
     980             : 
     981           1 :         multi_value.set_value(0, "123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     982           1 :         CATCH_REQUIRE(multi_value.size() == 1);
     983           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
     984           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
     985             : 
     986           1 :         multi_value.set_value(1, "456", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     987           1 :         CATCH_REQUIRE(multi_value.size() == 2);
     988           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
     989           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
     990           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "456");
     991           1 :         CATCH_REQUIRE(multi_value.get_long(1) == 456);
     992             : 
     993           1 :         multi_value.lock(false);
     994             : 
     995           1 :         multi_value.set_value(2, "789", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
     996           1 :         CATCH_REQUIRE(multi_value.size() == 2);
     997           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
     998           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
     999           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "456");
    1000           1 :         CATCH_REQUIRE(multi_value.get_long(1) == 456);
    1001             : 
    1002           1 :         multi_value.unlock();
    1003             : 
    1004           1 :         multi_value.set_value(2, "505", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1005           1 :         CATCH_REQUIRE(multi_value.size() == 3);
    1006           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
    1007           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
    1008           1 :         CATCH_REQUIRE(multi_value.get_value(1) == "456");
    1009           1 :         CATCH_REQUIRE(multi_value.get_long(1) == 456);
    1010           1 :         CATCH_REQUIRE(multi_value.get_value(2) == "505");
    1011           1 :         CATCH_REQUIRE(multi_value.get_long(2) == 505);
    1012             : 
    1013           1 :         multi_value.reset();
    1014           1 :         CATCH_REQUIRE(multi_value.size() == 0);
    1015             : 
    1016             :         // to verify that the f_integer was reset we kind of very much
    1017             :         // have to re-add a value
    1018             :         //
    1019           1 :         multi_value.set_value(0, "123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1020           1 :         CATCH_REQUIRE(multi_value.size() == 1);
    1021           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
    1022           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
    1023             :     CATCH_END_SECTION()
    1024           4 : }
    1025             : 
    1026             : 
    1027             : 
    1028           6 : CATCH_TEST_CASE("option_info_section_functions", "[option_info][valid][add][section]")
    1029             : {
    1030           8 :     CATCH_START_SECTION("Value without sections")
    1031           2 :         advgetopt::option_info value("no-sections", 'z');
    1032             : 
    1033           1 :         CATCH_REQUIRE(value.get_basename() == "no-sections");
    1034           1 :         CATCH_REQUIRE(value.get_section_name() == std::string());
    1035           1 :         CATCH_REQUIRE(value.get_section_name_list().empty());
    1036             :     CATCH_END_SECTION()
    1037             : 
    1038           8 :     CATCH_START_SECTION("Value with one section")
    1039           2 :         advgetopt::option_info value("one::section", 'o');
    1040             : 
    1041           1 :         CATCH_REQUIRE(value.get_basename() == "section");
    1042           1 :         CATCH_REQUIRE(value.get_section_name() == "one");
    1043           2 :         advgetopt::string_list_t sections(value.get_section_name_list());
    1044           1 :         CATCH_REQUIRE(sections.size() == 1);
    1045           1 :         CATCH_REQUIRE(sections[0] == "one");
    1046             :     CATCH_END_SECTION()
    1047             : 
    1048           8 :     CATCH_START_SECTION("Value with two sections")
    1049           2 :         advgetopt::option_info value("one::two::section", 't');
    1050             : 
    1051           1 :         CATCH_REQUIRE(value.get_basename() == "section");
    1052           1 :         CATCH_REQUIRE(value.get_section_name() == "one::two");
    1053           2 :         advgetopt::string_list_t sections(value.get_section_name_list());
    1054           1 :         CATCH_REQUIRE(sections.size() == 2);
    1055           1 :         CATCH_REQUIRE(sections[0] == "one");
    1056           1 :         CATCH_REQUIRE(sections[1] == "two");
    1057             :     CATCH_END_SECTION()
    1058             : 
    1059           8 :     CATCH_START_SECTION("Value with three sections")
    1060           2 :         advgetopt::option_info value("s1::s2::s3::section", 'f');
    1061             : 
    1062           1 :         CATCH_REQUIRE(value.get_basename() == "section");
    1063           1 :         CATCH_REQUIRE(value.get_section_name() == "s1::s2::s3");
    1064           2 :         advgetopt::string_list_t sections(value.get_section_name_list());
    1065           1 :         CATCH_REQUIRE(sections.size() == 3);
    1066           1 :         CATCH_REQUIRE(sections[0] == "s1");
    1067           1 :         CATCH_REQUIRE(sections[1] == "s2");
    1068           1 :         CATCH_REQUIRE(sections[2] == "s3");
    1069             :     CATCH_END_SECTION()
    1070           4 : }
    1071             : 
    1072             : 
    1073             : 
    1074             : 
    1075           3 : CATCH_TEST_CASE("redefine_option_short_name", "[options][valid][config]")
    1076             : {
    1077           2 :     CATCH_START_SECTION("Test adding '-<delta>' to '--config-dir'")
    1078             :     {
    1079           1 :         advgetopt::option const options[] =
    1080             :         {
    1081             :             advgetopt::define_option(
    1082             :                   advgetopt::Name("group")
    1083             :                 , advgetopt::ShortName('g')
    1084             :                 , advgetopt::Flags(advgetopt::command_flags<advgetopt::GETOPT_FLAG_REQUIRED>())
    1085             :                 , advgetopt::Help("group name.")
    1086             :             ),
    1087             :             advgetopt::end_options()
    1088             :         };
    1089             : 
    1090           1 :         advgetopt::options_environment environment_options;
    1091           1 :         environment_options.f_project_name = "unittest";
    1092           1 :         environment_options.f_options = options;
    1093           1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1094           1 :         environment_options.f_configuration_filename = "snaplog.conf";
    1095           1 :         environment_options.f_help_header = "Usage: test --config-dir";
    1096             : 
    1097           1 :         char const * cargv[] =
    1098             :         {
    1099             :             "/usr/bin/arguments",
    1100             :             "-g",
    1101             :             "m2osw",
    1102             :             "-L",
    1103             :             "-\xE2\xB5\xA0",        // Delta character
    1104             :             "/opt/advgetopt/config",
    1105             :             nullptr
    1106             :         };
    1107           1 :         int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
    1108           1 :         char ** argv = const_cast<char **>(cargv);
    1109             : 
    1110           2 :         advgetopt::getopt opt(environment_options);
    1111           1 :         opt.parse_program_name(argv);
    1112             : 
    1113           1 :         CATCH_REQUIRE(opt.get_option("config-dir") != nullptr);
    1114           1 :         CATCH_REQUIRE(opt.get_option("config-dir") == opt.get_option("config_dir"));
    1115           1 :         opt.set_short_name("config-dir", 0x2D60);
    1116             : 
    1117           1 :         opt.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1118             : 
    1119             :         // check that the result is valid
    1120             : 
    1121             :         // an invalid parameter, MUST NOT EXIST
    1122           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
    1123           1 :         CATCH_REQUIRE(opt.get_option("invalid-parameter") == opt.get_option("invalid_parameter"));
    1124           1 :         CATCH_REQUIRE(opt.get_option('Z') == nullptr);
    1125           1 :         CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
    1126           1 :         CATCH_REQUIRE(opt.get_default("invalid-parameter").empty());
    1127           1 :         CATCH_REQUIRE(opt.size("invalid-parameter") == 0);
    1128             : 
    1129             :         // the valid parameter
    1130           1 :         CATCH_REQUIRE(opt.get_option("group") != nullptr);
    1131           1 :         CATCH_REQUIRE(opt.get_option('g') == opt.get_option("group"));
    1132           1 :         CATCH_REQUIRE(opt.is_defined("group"));
    1133           1 :         CATCH_REQUIRE(opt.get_string("group") == "m2osw");
    1134           1 :         CATCH_REQUIRE(opt.get_string("group", 0) == "m2osw");
    1135           1 :         CATCH_REQUIRE(opt.get_default("group").empty());
    1136           1 :         CATCH_REQUIRE(opt.size("group") == 1);
    1137             : 
    1138             :         // the license system parameter
    1139           1 :         CATCH_REQUIRE(opt.get_option("license") != nullptr);
    1140           1 :         CATCH_REQUIRE(opt.get_option('L') == opt.get_option("license"));
    1141           1 :         CATCH_REQUIRE(opt.is_defined("license"));
    1142           1 :         CATCH_REQUIRE(opt.get_default("license").empty());
    1143           1 :         CATCH_REQUIRE(opt.size("license") == 1);
    1144             : 
    1145             :         // the config-dir system parameter
    1146           1 :         CATCH_REQUIRE(opt.get_option("config-dir") != nullptr);
    1147           1 :         CATCH_REQUIRE(opt.get_option(static_cast<advgetopt::short_name_t>(0x2D60)) == opt.get_option("config-dir"));
    1148           1 :         CATCH_REQUIRE(opt.is_defined("config-dir"));
    1149           1 :         CATCH_REQUIRE(opt.get_default("config-dir").empty());
    1150           1 :         CATCH_REQUIRE(opt.size("config-dir") == 1);
    1151           1 :         CATCH_REQUIRE(opt.get_string("config-dir") == "/opt/advgetopt/config");
    1152             : 
    1153             :         // other parameters
    1154           1 :         CATCH_REQUIRE(opt.get_program_name() == "arguments");
    1155           1 :         CATCH_REQUIRE(opt.get_program_fullname() == "/usr/bin/arguments");
    1156             :     }
    1157             :     CATCH_END_SECTION()
    1158           1 : }
    1159             : 
    1160             : 
    1161             : 
    1162             : 
    1163             : 
    1164             : 
    1165             : 
    1166             : 
    1167             : 
    1168          18 : CATCH_TEST_CASE("invalid_option_info", "[option_info][invalid]")
    1169             : {
    1170          32 :     CATCH_START_SECTION("No name")
    1171           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1172             :                   advgetopt::option_info("")
    1173             :                 , advgetopt::getopt_logic_error
    1174             :                 , Catch::Matchers::ExceptionMessage(
    1175             :                           "getopt_logic_error: option_info::option_info(): all options must at least have a long name."));
    1176             : 
    1177           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1178             :                   advgetopt::option_info("", 'v')
    1179             :                 , advgetopt::getopt_logic_error
    1180             :                 , Catch::Matchers::ExceptionMessage(
    1181             :                           "getopt_logic_error: option_info::option_info(): all options must at least have a long name (short name: 'v'.)"));
    1182             : 
    1183           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1184             :                   advgetopt::option_info(std::string())
    1185             :                 , advgetopt::getopt_logic_error
    1186             :                 , Catch::Matchers::ExceptionMessage(
    1187             :                           "getopt_logic_error: option_info::option_info(): all options must at least have a long name."));
    1188             : 
    1189           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1190             :                   advgetopt::option_info(std::string(), 'p')
    1191             :                 , advgetopt::getopt_logic_error
    1192             :                 , Catch::Matchers::ExceptionMessage(
    1193             :                           "getopt_logic_error: option_info::option_info(): all options must at least have a long name (short name: 'p'.)"));
    1194             :     CATCH_END_SECTION()
    1195             : 
    1196          32 :     CATCH_START_SECTION("Default with short name")
    1197           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1198             :                   advgetopt::option_info("--", 'f')
    1199             :                 , advgetopt::getopt_logic_error
    1200             :                 , Catch::Matchers::ExceptionMessage(
    1201             :                           "getopt_logic_error: option_info::option_info(): the default parameter \"--\" cannot include a short name ('f'.)"));
    1202             :     CATCH_END_SECTION()
    1203             : 
    1204          32 :     CATCH_START_SECTION("Long name cannot start with a dash (-)")
    1205           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1206             :                   advgetopt::option_info("--dashes")
    1207             :                 , advgetopt::getopt_logic_error
    1208             :                 , Catch::Matchers::ExceptionMessage(
    1209             :                           "getopt_logic_error: option_info::option_info(): an option cannot start with a dash (-), \"--dashes\" is not valid."));
    1210             :     CATCH_END_SECTION()
    1211             : 
    1212          32 :     CATCH_START_SECTION("Short name cannot be a dash (-)")
    1213           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1214             :                   advgetopt::option_info("dash", '-')
    1215             :                 , advgetopt::getopt_logic_error
    1216             :                 , Catch::Matchers::ExceptionMessage(
    1217             :                           "getopt_logic_error: option_info::option_info(): the short name of an option cannot be the dash (-)."));
    1218             :     CATCH_END_SECTION()
    1219             : 
    1220          32 :     CATCH_START_SECTION("Set value with undefined source")
    1221           2 :         advgetopt::option_info verbose("verbose", 'v');
    1222           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1223             :                   verbose.set_value(0, "true", advgetopt::option_source_t::SOURCE_UNDEFINED)
    1224             :                 , advgetopt::getopt_logic_error
    1225             :                 , Catch::Matchers::ExceptionMessage(
    1226             :                           "getopt_logic_error: option_info::set_value(): called with SOURCE_UNDEFINED (5)."));
    1227             :     CATCH_END_SECTION()
    1228             : 
    1229          32 :     CATCH_START_SECTION("Set multiple values with undefined source")
    1230           2 :         advgetopt::option_info verbose("verbose", 'v');
    1231           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1232             :                   verbose.set_multiple_values("a,b,c", advgetopt::option_source_t::SOURCE_UNDEFINED)
    1233             :                 , advgetopt::getopt_logic_error
    1234             :                 , Catch::Matchers::ExceptionMessage(
    1235             :                           "getopt_logic_error: option_info::set_multiple_values(): called with SOURCE_UNDEFINED (5)."));
    1236             :     CATCH_END_SECTION()
    1237             : 
    1238          32 :     CATCH_START_SECTION("Get value when undefined")
    1239           2 :         advgetopt::option_info verbose("verbose", 'v');
    1240           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1241             :                   verbose.get_value()
    1242             :                 , advgetopt::getopt_undefined
    1243             :                 , Catch::Matchers::ExceptionMessage(
    1244             :                           "getopt_exception: option_info::get_value(): no value at index 0 (idx >= 0) for --verbose so you can't get this value."));
    1245             :     CATCH_END_SECTION()
    1246             : 
    1247          32 :     CATCH_START_SECTION("Get long when undefined")
    1248           2 :         advgetopt::option_info verbose("verbose", 'v');
    1249           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1250             :                   verbose.get_long()
    1251             :                 , advgetopt::getopt_undefined
    1252             :                 , Catch::Matchers::ExceptionMessage(
    1253             :                           "getopt_exception: option_info::get_long(): no value at index 0 (idx >= 0) for --verbose so you can't get this value."));
    1254             :     CATCH_END_SECTION()
    1255             : 
    1256          32 :     CATCH_START_SECTION("Check alias of alias")
    1257           2 :         advgetopt::option_info::pointer_t option(std::make_shared<advgetopt::option_info>("option", 'o'));
    1258           2 :         advgetopt::option_info alias("alias", 'a');
    1259             : 
    1260           1 :         option->add_flag(advgetopt::GETOPT_FLAG_ALIAS);
    1261             : 
    1262           1 :         CATCH_REQUIRE(alias.get_alias_destination() == nullptr);
    1263             : 
    1264           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1265             :                   alias.set_alias_destination(option)
    1266             :                 , advgetopt::getopt_invalid
    1267             :                 , Catch::Matchers::ExceptionMessage(
    1268             :                           "getopt_exception: option_info::set_alias(): you can't set an alias as"
    1269             :                           " an alias of another option."));
    1270             : 
    1271           1 :         CATCH_REQUIRE(alias.get_alias_destination() == nullptr);
    1272             :     CATCH_END_SECTION()
    1273             : 
    1274          32 :     CATCH_START_SECTION("Set value, verify multiple strings (with MULTIPLE)")
    1275           2 :         advgetopt::option_info multi_value("names", 'n');
    1276             : 
    1277           1 :         multi_value.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
    1278             : 
    1279           1 :         CATCH_REQUIRE(multi_value.size() == 0);
    1280             : 
    1281           1 :         multi_value.set_value(0, "value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1282           1 :         CATCH_REQUIRE(multi_value.size() == 1);
    1283           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
    1284           1 :         CATCH_REQUIRE(multi_value.source() == advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1285             : 
    1286           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1287             :                   multi_value.set_value(2, "value two", advgetopt::option_source_t::SOURCE_COMMAND_LINE)
    1288             :                 , advgetopt::getopt_logic_error
    1289             :                 , Catch::Matchers::ExceptionMessage(
    1290             :                     "getopt_logic_error: option_info::set_value(): no value at index 2 and it is not the last available index + 1 (idx > 1) so you can't set this value (try add_value() maybe?)."));
    1291             : 
    1292           1 :         CATCH_REQUIRE(multi_value.size() == 1);
    1293           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "value one");
    1294             :     CATCH_END_SECTION()
    1295             : 
    1296          32 :     CATCH_START_SECTION("Set value, verify multiple integers (with MULTIPLE)")
    1297           2 :         advgetopt::option_info multi_value("names", 'n');
    1298             : 
    1299           1 :         multi_value.add_flag(advgetopt::GETOPT_FLAG_MULTIPLE);
    1300             : 
    1301           1 :         CATCH_REQUIRE(multi_value.size() == 0);
    1302             : 
    1303           1 :         multi_value.set_value(0, "123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1304           1 :         CATCH_REQUIRE(multi_value.size() == 1);
    1305           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
    1306           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
    1307             : 
    1308           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1309             :                   multi_value.set_value(2, "456", advgetopt::option_source_t::SOURCE_COMMAND_LINE)
    1310             :                 , advgetopt::getopt_logic_error
    1311             :                 , Catch::Matchers::ExceptionMessage(
    1312             :                     "getopt_logic_error: option_info::set_value(): no value at index 2 and it is not the last available index + 1 (idx > 1) so you can't set this value (try add_value() maybe?)."));
    1313             : 
    1314           1 :         CATCH_REQUIRE(multi_value.size() == 1);
    1315           1 :         CATCH_REQUIRE(multi_value.get_value(0) == "123");
    1316           1 :         CATCH_REQUIRE(multi_value.get_long(0) == 123);
    1317             :     CATCH_END_SECTION()
    1318             : 
    1319          32 :     CATCH_START_SECTION("Set value, verify multiple strings (without MULTIPLE)")
    1320           2 :         advgetopt::option_info one_value("names", 'n');
    1321             : 
    1322           1 :         CATCH_REQUIRE(one_value.size() == 0);
    1323             : 
    1324           1 :         one_value.set_value(0, "value one", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1325           1 :         CATCH_REQUIRE(one_value.size() == 1);
    1326           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value one");
    1327             : 
    1328           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1329             :                   one_value.set_value(1, "value two", advgetopt::option_source_t::SOURCE_COMMAND_LINE)
    1330             :                 , advgetopt::getopt_logic_error
    1331             :                 , Catch::Matchers::ExceptionMessage(
    1332             :                     "getopt_logic_error: option_info::set_value(): single value option \"--names\" does not accepts index 1 which is not 0."));
    1333             : 
    1334           1 :         CATCH_REQUIRE(one_value.size() == 1);
    1335           1 :         CATCH_REQUIRE(one_value.get_value(0) == "value one");
    1336             :     CATCH_END_SECTION()
    1337             : 
    1338          32 :     CATCH_START_SECTION("Set value, verify multiple integers (without MULTIPLE)")
    1339           2 :         advgetopt::option_info one_value("names", 'n');
    1340             : 
    1341           1 :         CATCH_REQUIRE(one_value.size() == 0);
    1342             : 
    1343           1 :         one_value.set_value(0, "123", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1344           1 :         CATCH_REQUIRE(one_value.size() == 1);
    1345           1 :         CATCH_REQUIRE(one_value.get_value(0) == "123");
    1346           1 :         CATCH_REQUIRE(one_value.get_long(0) == 123);
    1347             : 
    1348           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1349             :                   one_value.set_value(1, "456", advgetopt::option_source_t::SOURCE_COMMAND_LINE)
    1350             :                 , advgetopt::getopt_logic_error
    1351             :                 , Catch::Matchers::ExceptionMessage(
    1352             :                     "getopt_logic_error: option_info::set_value(): single value option \"--names\" does not accepts index 1 which is not 0."));
    1353             : 
    1354           1 :         CATCH_REQUIRE(one_value.size() == 1);
    1355           1 :         CATCH_REQUIRE(one_value.get_value(0) == "123");
    1356           1 :         CATCH_REQUIRE(one_value.get_long(0) == 123);
    1357             :     CATCH_END_SECTION()
    1358             : 
    1359          32 :     CATCH_START_SECTION("Long number too large")
    1360           2 :         advgetopt::option_info size("size", 's');
    1361             : 
    1362           1 :         CATCH_REQUIRE(size.size() == 0);
    1363             : 
    1364             :         // really too large
    1365             :         //
    1366           1 :         size.set_value(0, "100000000000000000000", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1367           1 :         CATCH_REQUIRE(size.size() == 1);
    1368           1 :         CATCH_REQUIRE(size.get_value(0) == "100000000000000000000");
    1369             : 
    1370           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number (100000000000000000000) in parameter --size at offset 0.");
    1371           1 :         CATCH_REQUIRE(size.get_long(0) == -1);
    1372           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
    1373             : 
    1374             :         // too large by 1
    1375             :         //
    1376           1 :         size.set_value(0, "9223372036854775808", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1377           1 :         CATCH_REQUIRE(size.size() == 1);
    1378           1 :         CATCH_REQUIRE(size.get_value(0) == "9223372036854775808");
    1379             : 
    1380           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number (9223372036854775808) in parameter --size at offset 0.");
    1381           1 :         CATCH_REQUIRE(size.get_long(0) == -1);
    1382           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
    1383             : 
    1384             :         // too small by 1
    1385             :         //
    1386           1 :         size.set_value(0, "-9223372036854775809", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1387           1 :         CATCH_REQUIRE(size.size() == 1);
    1388           1 :         CATCH_REQUIRE(size.get_value(0) == "-9223372036854775809");
    1389             : 
    1390           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number (-9223372036854775809) in parameter --size at offset 0.");
    1391           1 :         CATCH_REQUIRE(size.get_long(0) == -1);
    1392           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
    1393             : 
    1394             :         // not a valid number
    1395             :         //
    1396           1 :         size.set_value(0, "97 potatoes", advgetopt::option_source_t::SOURCE_COMMAND_LINE);
    1397           1 :         CATCH_REQUIRE(size.size() == 1);
    1398           1 :         CATCH_REQUIRE(size.get_value(0) == "97 potatoes");
    1399             : 
    1400           1 :         SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number (97 potatoes) in parameter --size at offset 0.");
    1401           1 :         CATCH_REQUIRE(size.get_long(0) == -1);
    1402           1 :         SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
    1403             :     CATCH_END_SECTION()
    1404             : 
    1405          32 :     CATCH_START_SECTION("Check multiple separators")
    1406           2 :         advgetopt::option_info separators("names", 'n');
    1407             : 
    1408           1 :         advgetopt::string_list_t list{
    1409             :             ",",
    1410             :             ";",
    1411             :             " ",
    1412             :             "^"
    1413           2 :         };
    1414           1 :         separators.set_multiple_separators(list);
    1415             : 
    1416           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1417             :                   separators.set_multiple_values("n1,n2;n3 n4 ^ n5", advgetopt::option_source_t::SOURCE_COMMAND_LINE)
    1418             :                 , advgetopt::getopt_logic_error
    1419             :                 , Catch::Matchers::ExceptionMessage(
    1420             :                     "getopt_logic_error: option_info::set_multiple_value(): parameter --names expects zero or one parameter."
    1421             :                     " The set_multiple_value() function should not be called with parameters that only accept one value."));
    1422             : 
    1423           1 :         CATCH_REQUIRE(separators.size() == 0);
    1424             :     CATCH_END_SECTION()
    1425             : 
    1426          32 :     CATCH_START_SECTION("Check multiple separators")
    1427           2 :         advgetopt::option_info auto_validate("validator", 'C');
    1428           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1429             :                   auto_validate.set_validator("regex('^[a-z]+$/'")
    1430             :                 , advgetopt::getopt_logic_error
    1431             :                 , Catch::Matchers::ExceptionMessage(
    1432             :                     "getopt_logic_error: invalid validator parameter definition: \"regex('^[a-z]+$/'\", the ')' is missing."));
    1433             :     CATCH_END_SECTION()
    1434          16 : }
    1435             : 
    1436             : 
    1437             : 
    1438             : 
    1439           4 : CATCH_TEST_CASE("check_invalid_config_dir_short_names", "[arguments][invalid][getopt][config]")
    1440             : {
    1441           4 :     CATCH_START_SECTION("Trying to set NO_SHORT_NAME as '--config-dir' short name (option_info)")
    1442             :     {
    1443           1 :         advgetopt::option const options[] =
    1444             :         {
    1445             :             advgetopt::define_option(
    1446             :                   advgetopt::Name("print")
    1447             :                 , advgetopt::ShortName(U'p')
    1448             :                 , advgetopt::Flags(advgetopt::command_flags<>())
    1449             :                 , advgetopt::Help("output filename.")
    1450             :             ),
    1451             :             advgetopt::end_options()
    1452             :         };
    1453             : 
    1454           1 :         advgetopt::options_environment environment_options;
    1455           1 :         environment_options.f_project_name = "unittest";
    1456           1 :         environment_options.f_options = options;
    1457           1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1458           1 :         environment_options.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
    1459           1 :         environment_options.f_configuration_filename = "snapwatchdog.conf";
    1460           1 :         environment_options.f_help_header = "Usage: test --config-dir";
    1461             : 
    1462           2 :         advgetopt::getopt opt(environment_options);
    1463             : 
    1464           2 :         advgetopt::option_info::pointer_t o(opt.get_option("config-dir"));
    1465           1 :         CATCH_REQUIRE(o != nullptr);
    1466           1 :         CATCH_REQUIRE(o->get_short_name() == advgetopt::NO_SHORT_NAME);
    1467             : 
    1468           1 :         opt.set_short_name("config-dir", advgetopt::NO_SHORT_NAME);
    1469           1 :         CATCH_REQUIRE(o->get_short_name() == advgetopt::NO_SHORT_NAME);
    1470             :     }
    1471             :     CATCH_END_SECTION()
    1472             : 
    1473           4 :     CATCH_START_SECTION("Trying to change short name of '--version' (option_info)")
    1474             :     {
    1475           1 :         advgetopt::option const options[] =
    1476             :         {
    1477             :             advgetopt::define_option(
    1478             :                   advgetopt::Name("print")
    1479             :                 , advgetopt::ShortName('p')
    1480             :                 , advgetopt::Flags(advgetopt::command_flags<>())
    1481             :                 , advgetopt::Help("print all info.")
    1482             :             ),
    1483             :             advgetopt::end_options()
    1484             :         };
    1485             : 
    1486           1 :         advgetopt::options_environment environment_options;
    1487           1 :         environment_options.f_project_name = "unittest";
    1488           1 :         environment_options.f_options = options;
    1489           1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1490           1 :         environment_options.f_configuration_filename = "";
    1491           1 :         environment_options.f_help_header = "Usage: test --config-dir";
    1492             : 
    1493           2 :         advgetopt::getopt opt(environment_options);
    1494             : 
    1495           2 :         advgetopt::option_info::pointer_t o(opt.get_option("version"));
    1496           1 :         CATCH_REQUIRE(o != nullptr);
    1497           1 :         CATCH_REQUIRE(o->get_short_name() == U'V');
    1498           1 :         CATCH_REQUIRE(o == opt.get_option(U'V'));
    1499           1 :         CATCH_REQUIRE(opt.get_option(U'v') == nullptr);
    1500             : 
    1501           1 :         opt.set_short_name("version", U'V');   // keep uppercase...
    1502           1 :         CATCH_REQUIRE(o->get_short_name() == U'V');
    1503           1 :         CATCH_REQUIRE(o == opt.get_option(U'V'));
    1504           1 :         CATCH_REQUIRE(opt.get_option(U'v') == nullptr);
    1505             : 
    1506           1 :         opt.set_short_name("version", U'v');   // set to lowercase...
    1507           1 :         CATCH_REQUIRE(o->get_short_name() == U'v');
    1508           1 :         CATCH_REQUIRE(o == opt.get_option(U'v'));
    1509           1 :         CATCH_REQUIRE(opt.get_option(U'V') == nullptr);
    1510             : 
    1511           1 :         opt.set_short_name("version", advgetopt::NO_SHORT_NAME);   // remove completely...
    1512           1 :         CATCH_REQUIRE(o->get_short_name() ==advgetopt::NO_SHORT_NAME);
    1513           1 :         CATCH_REQUIRE(opt.get_option(U'V') == nullptr);
    1514           1 :         CATCH_REQUIRE(opt.get_option(U'v') == nullptr);
    1515             :     }
    1516             :     CATCH_END_SECTION()
    1517           2 : }
    1518             : 
    1519             : 
    1520             : 
    1521             : 
    1522           3 : CATCH_TEST_CASE("check_option_callbacks", "[arguments][getopt][config][callback]")
    1523             : {
    1524           2 :     CATCH_START_SECTION("Check option callbacks")
    1525             :     {
    1526           1 :         advgetopt::option const options[] =
    1527             :         {
    1528             :             advgetopt::define_option(
    1529             :                   advgetopt::Name("print")
    1530             :                 , advgetopt::ShortName(U'p')
    1531             :                 , advgetopt::Flags(advgetopt::command_flags<advgetopt::GETOPT_FLAG_DYNAMIC_CONFIGURATION>())
    1532             :                 , advgetopt::Help("output filename.")
    1533             :             ),
    1534             :             advgetopt::end_options()
    1535             :         };
    1536             : 
    1537           1 :         advgetopt::options_environment environment_options;
    1538           1 :         environment_options.f_project_name = "unittest";
    1539           1 :         environment_options.f_options = options;
    1540           1 :         environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
    1541           1 :         environment_options.f_configuration_filename = "snapwatchdog.conf";
    1542           1 :         environment_options.f_help_header = "Usage: test --config-dir";
    1543             : 
    1544           2 :         advgetopt::getopt opt(environment_options);
    1545             : 
    1546           4 :         struct print_expected
    1547             :         {
    1548             :         public:
    1549           8 :             void set_value(std::string const & value)
    1550             :             {
    1551           8 :                 f_value = value;
    1552           8 :             }
    1553             : 
    1554           6 :             std::string const & value() const
    1555             :             {
    1556           6 :                 return f_value;
    1557             :             }
    1558             : 
    1559             :         private:
    1560             :             std::string f_value = std::string();
    1561             :         };
    1562             : 
    1563             :         struct print_callback
    1564             :         {
    1565             :         public:
    1566           2 :             print_callback(print_expected * expected)
    1567           2 :                 : f_expected(expected)
    1568             :             {
    1569           2 :             }
    1570             : 
    1571           6 :             void operator() (advgetopt::option_info const & opt)
    1572             :             {
    1573           6 :                 CATCH_REQUIRE(f_expected->value() == opt.get_value());
    1574           6 :             }
    1575             : 
    1576             :         private:
    1577             :             print_expected *    f_expected = nullptr;
    1578             :         };
    1579             : 
    1580           2 :         print_expected expected1;
    1581           1 :         print_callback cb1(&expected1);
    1582             : 
    1583           2 :         advgetopt::option_info::pointer_t print(opt.get_option("print"));
    1584           1 :         CATCH_REQUIRE(print != nullptr);
    1585           1 :         advgetopt::option_info::callback_id_t const id1(print->add_callback(cb1));
    1586             : 
    1587           1 :         expected1.set_value("color");
    1588           1 :         print->set_value(0, "color");
    1589             : 
    1590             :         // test with a second callback, both are hit
    1591             :         //
    1592           2 :         print_expected expected2;
    1593           1 :         print_callback cb2(&expected2);
    1594           1 :         advgetopt::option_info::callback_id_t const id2(print->add_callback(cb2));
    1595             : 
    1596           1 :         expected1.set_value("black & white");
    1597           1 :         expected2.set_value("black & white");
    1598           1 :         print->set_value(0, "black & white");
    1599             : 
    1600             :         // call the remove without a valid identifier so a change still
    1601             :         // applies
    1602             :         //
    1603           1 :         print->remove_callback(id2 + 10);
    1604             : 
    1605           1 :         expected1.set_value("stipple");
    1606           1 :         expected2.set_value("stipple");
    1607           1 :         print->set_value(0, "stipple");
    1608             : 
    1609             :         // remove the first callback and try again
    1610             :         //
    1611           1 :         print->remove_callback(id1);
    1612             : 
    1613           1 :         expected1.set_value("ignored");     // this was removed
    1614           1 :         expected2.set_value("dithering");
    1615           1 :         print->set_value(0, "dithering");
    1616             : 
    1617             :         // remove the second callback and try again
    1618             :         //
    1619           1 :         print->remove_callback(id2);
    1620             : 
    1621           1 :         expected2.set_value("not called anymore either");
    1622           1 :         print->set_value(0, "cmyk");
    1623             :     }
    1624             :     CATCH_END_SECTION()
    1625           7 : }
    1626             : 
    1627             : 
    1628             : 
    1629             : 
    1630             : 
    1631             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13