LCOV - code coverage report
Current view: top level - tests - catch_variables.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 110 110
Test Date: 2026-01-18 09:38:57 Functions: 100.0 % 3 3
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright (c) 2006-2025  Made to Order Software Corp.  All Rights Reserved
       2              : //
       3              : // https://snapwebsites.org/project/advgetopt
       4              : // contact@m2osw.com
       5              : //
       6              : // This program is free software; you can redistribute it and/or modify
       7              : // it under the terms of the GNU General Public License as published by
       8              : // the Free Software Foundation; either version 2 of the License, or
       9              : // (at your option) any later version.
      10              : //
      11              : // This program is distributed in the hope that it will be useful,
      12              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14              : // GNU General Public License for more details.
      15              : //
      16              : // You should have received a copy of the GNU General Public License along
      17              : // with this program; if not, write to the Free Software Foundation, Inc.,
      18              : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19              : 
      20              : // advgetopt
      21              : //
      22              : #include    <advgetopt/variables.h>
      23              : 
      24              : #include    <advgetopt/exception.h>
      25              : 
      26              : 
      27              : // self
      28              : //
      29              : #include    "catch_main.h"
      30              : 
      31              : 
      32              : // C++
      33              : //
      34              : #include    <fstream>
      35              : #include    <iomanip>
      36              : 
      37              : 
      38              : // last include
      39              : //
      40              : #include    <snapdev/poison.h>
      41              : 
      42              : 
      43              : 
      44            1 : CATCH_TEST_CASE("variables", "[variables][valid]")
      45              : {
      46            1 :     CATCH_START_SECTION("variables: check the variables class")
      47              :     {
      48            1 :         advgetopt::variables vars;
      49              : 
      50              :         // not set yet
      51            3 :         CATCH_REQUIRE(vars.get_variable("first-variable") == std::string());
      52            1 :         CATCH_REQUIRE(vars.get_variables().empty());
      53              : 
      54            3 :         CATCH_REQUIRE_FALSE(vars.has_variable("first_variable"));
      55            5 :         vars.set_variable("first_variable", "it works");
      56            1 :         CATCH_REQUIRE(vars.get_variables().size() == 1);
      57            3 :         CATCH_REQUIRE(vars.has_variable("first_variable"));
      58            3 :         CATCH_REQUIRE(vars.has_variable("first-variable"));
      59            3 :         CATCH_REQUIRE(vars.get_variable("first_variable") == "it works");
      60            3 :         CATCH_REQUIRE(vars.get_variable("first-variable") == "it works");
      61              : 
      62            3 :         CATCH_REQUIRE_FALSE(vars.has_variable("second::variable"));
      63            5 :         vars.set_variable("second::variable", "double colon");
      64            1 :         CATCH_REQUIRE(vars.get_variables().size() == 2);
      65            3 :         CATCH_REQUIRE(vars.has_variable("second.variable"));
      66            3 :         CATCH_REQUIRE(vars.has_variable("second..variable"));
      67            3 :         CATCH_REQUIRE(vars.has_variable("second...variable"));
      68            3 :         CATCH_REQUIRE(vars.has_variable("second....variable"));
      69            3 :         CATCH_REQUIRE(vars.has_variable("second:variable"));
      70            3 :         CATCH_REQUIRE(vars.has_variable("second::variable"));
      71            3 :         CATCH_REQUIRE(vars.has_variable("second:::variable"));
      72            3 :         CATCH_REQUIRE(vars.has_variable("second::::variable"));
      73            3 :         CATCH_REQUIRE(vars.get_variable("second.variable") == "double colon");
      74            3 :         CATCH_REQUIRE(vars.get_variable("second..variable") == "double colon");
      75            3 :         CATCH_REQUIRE(vars.get_variable("second...variable") == "double colon");
      76            3 :         CATCH_REQUIRE(vars.get_variable("second....variable") == "double colon");
      77            3 :         CATCH_REQUIRE(vars.get_variable("second:variable") == "double colon");
      78            3 :         CATCH_REQUIRE(vars.get_variable("second::variable") == "double colon");
      79            3 :         CATCH_REQUIRE(vars.get_variable("second:::variable") == "double colon");
      80            3 :         CATCH_REQUIRE(vars.get_variable("second::::variable") == "double colon");
      81              : 
      82            3 :         CATCH_REQUIRE_FALSE(vars.has_variable("third::::variable"));
      83            5 :         vars.set_variable("third::::variable", "scope operator");
      84            1 :         CATCH_REQUIRE(vars.get_variables().size() == 3);
      85            3 :         CATCH_REQUIRE(vars.has_variable("third::variable"));
      86            3 :         CATCH_REQUIRE(vars.get_variable("third::variable") == "scope operator");
      87              : 
      88              :         // change value
      89            5 :         vars.set_variable("first_variable", "replaced value");
      90            3 :         CATCH_REQUIRE(vars.get_variable("first_variable") == "replaced value");
      91            1 :         CATCH_REQUIRE(vars.get_variables().size() == 3);
      92              : 
      93              :         // attempt changing value when already set
      94            5 :         vars.set_variable("first_variable", "ignored value", advgetopt::assignment_t::ASSIGNMENT_OPTIONAL);
      95            3 :         CATCH_REQUIRE(vars.get_variable("first_variable") == "replaced value");
      96            1 :         CATCH_REQUIRE(vars.get_variables().size() == 3);
      97              : 
      98            1 :         advgetopt::variables::variable_t list(vars.get_variables());
      99            4 :         for(auto l : list)
     100              :         {
     101            3 :             if(l.first == "first-variable")
     102              :             {
     103            1 :                 CATCH_REQUIRE(l.second == "replaced value");
     104              :             }
     105            2 :             else if(l.first == "second::variable")
     106              :             {
     107            1 :                 CATCH_REQUIRE(l.second == "double colon");
     108              :             }
     109              :             else
     110              :             {
     111              :                 // if not 1st or 2nd, it has to be 3rd
     112              :                 //
     113            1 :                 CATCH_REQUIRE(l.first == "third::variable");
     114            1 :                 CATCH_REQUIRE(l.second == "scope operator");
     115              :             }
     116            3 :         }
     117              : 
     118              :         // valid
     119              :         //
     120            3 :         std::string processed(vars.process_value("First Var = [${first-variable}]"));
     121            1 :         CATCH_REQUIRE(processed == "First Var = [replaced value]");
     122              : 
     123              :         // missing '}'
     124              :         //
     125            3 :         processed = vars.process_value("First Var = [${first-variable]");
     126            1 :         CATCH_REQUIRE(processed == "First Var = [${first-variable]");
     127              : 
     128            5 :         vars.set_variable("loopA", "ref ${loopB}", advgetopt::assignment_t::ASSIGNMENT_OPTIONAL);
     129            3 :         CATCH_REQUIRE(vars.get_variable("loopA") == "ref ${loopB}");
     130            1 :         CATCH_REQUIRE(vars.get_variables().size() == 4);
     131              : 
     132            5 :         vars.set_variable("loopB", "ref ${loopA}", advgetopt::assignment_t::ASSIGNMENT_OPTIONAL);
     133            3 :         CATCH_REQUIRE(vars.get_variable("loopB") == "ref ${loopA}");
     134            1 :         CATCH_REQUIRE(vars.get_variables().size() == 5);
     135              : 
     136            3 :         processed = vars.process_value("Looping like crazy: ${loopA}");
     137            1 :         CATCH_REQUIRE(processed == "Looping like crazy: ref ref <variable \"loopA\" loops>");
     138              : 
     139            3 :         processed = vars.process_value("Looping like crazy: ${loopB}");
     140            1 :         CATCH_REQUIRE(processed == "Looping like crazy: ref ref <variable \"loopB\" loops>");
     141              : 
     142            5 :         vars.set_variable("cummulative", "start", advgetopt::assignment_t::ASSIGNMENT_NEW);
     143            3 :         CATCH_REQUIRE(vars.get_variable("cummulative") == "start");
     144            1 :         CATCH_REQUIRE(vars.get_variables().size() == 6);
     145            5 :         vars.set_variable("cummulative", "-middle-", advgetopt::assignment_t::ASSIGNMENT_APPEND);
     146            3 :         CATCH_REQUIRE(vars.get_variable("cummulative") == "start-middle-");
     147            1 :         CATCH_REQUIRE(vars.get_variables().size() == 6);
     148            5 :         vars.set_variable("cummulative", "end", advgetopt::assignment_t::ASSIGNMENT_APPEND);
     149            3 :         CATCH_REQUIRE(vars.get_variable("cummulative") == "start-middle-end");
     150            1 :         CATCH_REQUIRE(vars.get_variables().size() == 6);
     151              : 
     152            5 :         vars.set_variable("additive", "beg", advgetopt::assignment_t::ASSIGNMENT_APPEND);
     153            3 :         CATCH_REQUIRE(vars.get_variable("additive") == "beg");
     154            1 :         CATCH_REQUIRE(vars.get_variables().size() == 7);
     155            5 :         vars.set_variable("additive", ":mid", advgetopt::assignment_t::ASSIGNMENT_APPEND);
     156            3 :         CATCH_REQUIRE(vars.get_variable("additive") == "beg:mid");
     157            1 :         CATCH_REQUIRE(vars.get_variables().size() == 7);
     158            5 :         vars.set_variable("additive", ":end", advgetopt::assignment_t::ASSIGNMENT_APPEND);
     159            3 :         CATCH_REQUIRE(vars.get_variable("additive") == "beg:mid:end");
     160            1 :         CATCH_REQUIRE(vars.get_variables().size() == 7);
     161            1 :     }
     162            1 :     CATCH_END_SECTION()
     163            1 : }
     164              : 
     165              : 
     166            4 : CATCH_TEST_CASE("invalid_variable_name", "[variables][invalid]")
     167              : {
     168            4 :     CATCH_START_SECTION("invalid_variable_name: parsing an empty section name throws")
     169            8 :         CATCH_REQUIRE_THROWS_MATCHES(
     170              :                   advgetopt::variables::canonicalize_variable_name(":bad_start")
     171              :                 , advgetopt::getopt_invalid
     172              :                 , Catch::Matchers::ExceptionMessage(
     173              :                       "getopt_exception: found an empty section name in \":bad_start\"."));
     174            4 :     CATCH_END_SECTION()
     175              : 
     176            4 :     CATCH_START_SECTION("invalid_variable_name: parsing first section name that start with a digit fails")
     177            8 :         CATCH_REQUIRE_THROWS_MATCHES(
     178              :                   advgetopt::variables::canonicalize_variable_name("3::bad_start")
     179              :                 , advgetopt::getopt_invalid
     180              :                 , Catch::Matchers::ExceptionMessage(
     181              :                       "getopt_exception: a variable name or section name in \"3::bad_start\" starts with a digit, which is not allowed."));
     182            4 :     CATCH_END_SECTION()
     183              : 
     184            4 :     CATCH_START_SECTION("invalid_variable_name: parsing second section name that start with a digit fails")
     185            8 :         CATCH_REQUIRE_THROWS_MATCHES(
     186              :                   advgetopt::variables::canonicalize_variable_name("good::3::bad_section")
     187              :                 , advgetopt::getopt_invalid
     188              :                 , Catch::Matchers::ExceptionMessage(
     189              :                       "getopt_exception: a variable name or section name in \"good::3::bad_section\" starts with a digit, which is not allowed."));
     190            4 :     CATCH_END_SECTION()
     191              : 
     192            4 :     CATCH_START_SECTION("invalid_variable_name: parsing variable name that start with a digit fails")
     193            8 :         CATCH_REQUIRE_THROWS_MATCHES(
     194              :                   advgetopt::variables::canonicalize_variable_name("good::and_bad::9times")
     195              :                 , advgetopt::getopt_invalid
     196              :                 , Catch::Matchers::ExceptionMessage(
     197              :                       "getopt_exception: a variable name or section name in \"good::and_bad::9times\" starts with a digit, which is not allowed."));
     198            4 :     CATCH_END_SECTION()
     199            4 : }
     200              : 
     201              : 
     202            1 : CATCH_TEST_CASE("invalid_variable", "[variables][invalid]")
     203              : {
     204            1 :     CATCH_START_SECTION("invalid_variable: NEW assignment fails if variable exists")
     205              :     {
     206            1 :         advgetopt::variables vars;
     207              : 
     208            5 :         vars.set_variable("unique", "works", advgetopt::assignment_t::ASSIGNMENT_NEW);
     209            3 :         CATCH_REQUIRE(vars.get_variable("unique") == "works");
     210            1 :         CATCH_REQUIRE(vars.get_variables().size() == 1);
     211              : 
     212           11 :         CATCH_REQUIRE_THROWS_MATCHES(
     213              :                   vars.set_variable("unique", "fail", advgetopt::assignment_t::ASSIGNMENT_NEW)
     214              :                 , advgetopt::getopt_defined_twice
     215              :                 , Catch::Matchers::ExceptionMessage(
     216              :                       "getopt_exception: variable \"unique\" is already defined."));
     217            1 :     }
     218            1 :     CATCH_END_SECTION()
     219            1 : }
     220              : 
     221              : 
     222              : 
     223              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions