LCOV - code coverage report
Current view: top level - tests - option_info.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 892 892 100.0 %
Date: 2021-09-08 13:54:31 Functions: 24 24 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13