Line data Source code
1 : // Copyright (c) 2006-2024 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 : 45 : 46 : 47 1 : CATCH_TEST_CASE("variables", "[variables][valid]") 48 : { 49 1 : CATCH_START_SECTION("variables: check the variables class") 50 : { 51 1 : advgetopt::variables vars; 52 : 53 : // not set yet 54 1 : CATCH_REQUIRE(vars.get_variable("first-variable") == std::string()); 55 1 : CATCH_REQUIRE(vars.get_variables().empty()); 56 : 57 1 : CATCH_REQUIRE_FALSE(vars.has_variable("first_variable")); 58 1 : vars.set_variable("first_variable", "it works"); 59 1 : CATCH_REQUIRE(vars.get_variables().size() == 1); 60 1 : CATCH_REQUIRE(vars.has_variable("first_variable")); 61 1 : CATCH_REQUIRE(vars.has_variable("first-variable")); 62 1 : CATCH_REQUIRE(vars.get_variable("first_variable") == "it works"); 63 1 : CATCH_REQUIRE(vars.get_variable("first-variable") == "it works"); 64 : 65 1 : CATCH_REQUIRE_FALSE(vars.has_variable("second::variable")); 66 1 : vars.set_variable("second::variable", "double colon"); 67 1 : CATCH_REQUIRE(vars.get_variables().size() == 2); 68 1 : CATCH_REQUIRE(vars.has_variable("second.variable")); 69 1 : CATCH_REQUIRE(vars.has_variable("second..variable")); 70 1 : CATCH_REQUIRE(vars.has_variable("second...variable")); 71 1 : CATCH_REQUIRE(vars.has_variable("second....variable")); 72 1 : CATCH_REQUIRE(vars.has_variable("second:variable")); 73 1 : CATCH_REQUIRE(vars.has_variable("second::variable")); 74 1 : CATCH_REQUIRE(vars.has_variable("second:::variable")); 75 1 : CATCH_REQUIRE(vars.has_variable("second::::variable")); 76 1 : CATCH_REQUIRE(vars.get_variable("second.variable") == "double colon"); 77 1 : CATCH_REQUIRE(vars.get_variable("second..variable") == "double colon"); 78 1 : CATCH_REQUIRE(vars.get_variable("second...variable") == "double colon"); 79 1 : CATCH_REQUIRE(vars.get_variable("second....variable") == "double colon"); 80 1 : CATCH_REQUIRE(vars.get_variable("second:variable") == "double colon"); 81 1 : CATCH_REQUIRE(vars.get_variable("second::variable") == "double colon"); 82 1 : CATCH_REQUIRE(vars.get_variable("second:::variable") == "double colon"); 83 1 : CATCH_REQUIRE(vars.get_variable("second::::variable") == "double colon"); 84 : 85 1 : CATCH_REQUIRE_FALSE(vars.has_variable("third::::variable")); 86 1 : vars.set_variable("third::::variable", "scope operator"); 87 1 : CATCH_REQUIRE(vars.get_variables().size() == 3); 88 1 : CATCH_REQUIRE(vars.has_variable("third::variable")); 89 1 : CATCH_REQUIRE(vars.get_variable("third::variable") == "scope operator"); 90 : 91 : // change value 92 1 : vars.set_variable("first_variable", "replaced value"); 93 1 : CATCH_REQUIRE(vars.get_variable("first_variable") == "replaced value"); 94 1 : CATCH_REQUIRE(vars.get_variables().size() == 3); 95 : 96 : // attempt changing value when already set 97 1 : vars.set_variable("first_variable", "ignored value", advgetopt::assignment_t::ASSIGNMENT_OPTIONAL); 98 1 : CATCH_REQUIRE(vars.get_variable("first_variable") == "replaced value"); 99 1 : CATCH_REQUIRE(vars.get_variables().size() == 3); 100 : 101 1 : advgetopt::variables::variable_t list(vars.get_variables()); 102 4 : for(auto l : list) 103 : { 104 3 : if(l.first == "first-variable") 105 : { 106 1 : CATCH_REQUIRE(l.second == "replaced value"); 107 : } 108 2 : else if(l.first == "second::variable") 109 : { 110 1 : CATCH_REQUIRE(l.second == "double colon"); 111 : } 112 : else 113 : { 114 : // if not 1st or 2nd, it has to be 3rd 115 : // 116 1 : CATCH_REQUIRE(l.first == "third::variable"); 117 1 : CATCH_REQUIRE(l.second == "scope operator"); 118 : } 119 3 : } 120 : 121 : // valid 122 : // 123 3 : std::string processed(vars.process_value("First Var = [${first-variable}]")); 124 1 : CATCH_REQUIRE(processed == "First Var = [replaced value]"); 125 : 126 : // missing '}' 127 : // 128 1 : processed = vars.process_value("First Var = [${first-variable]"); 129 1 : CATCH_REQUIRE(processed == "First Var = [${first-variable]"); 130 : 131 1 : vars.set_variable("loopA", "ref ${loopB}", advgetopt::assignment_t::ASSIGNMENT_OPTIONAL); 132 1 : CATCH_REQUIRE(vars.get_variable("loopA") == "ref ${loopB}"); 133 1 : CATCH_REQUIRE(vars.get_variables().size() == 4); 134 : 135 1 : vars.set_variable("loopB", "ref ${loopA}", advgetopt::assignment_t::ASSIGNMENT_OPTIONAL); 136 1 : CATCH_REQUIRE(vars.get_variable("loopB") == "ref ${loopA}"); 137 1 : CATCH_REQUIRE(vars.get_variables().size() == 5); 138 : 139 1 : processed = vars.process_value("Looping like crazy: ${loopA}"); 140 1 : CATCH_REQUIRE(processed == "Looping like crazy: ref ref <variable \"loopA\" loops>"); 141 : 142 1 : processed = vars.process_value("Looping like crazy: ${loopB}"); 143 1 : CATCH_REQUIRE(processed == "Looping like crazy: ref ref <variable \"loopB\" loops>"); 144 : 145 1 : vars.set_variable("cummulative", "start", advgetopt::assignment_t::ASSIGNMENT_NEW); 146 1 : CATCH_REQUIRE(vars.get_variable("cummulative") == "start"); 147 1 : CATCH_REQUIRE(vars.get_variables().size() == 6); 148 1 : vars.set_variable("cummulative", "-middle-", advgetopt::assignment_t::ASSIGNMENT_APPEND); 149 1 : CATCH_REQUIRE(vars.get_variable("cummulative") == "start-middle-"); 150 1 : CATCH_REQUIRE(vars.get_variables().size() == 6); 151 1 : vars.set_variable("cummulative", "end", advgetopt::assignment_t::ASSIGNMENT_APPEND); 152 1 : CATCH_REQUIRE(vars.get_variable("cummulative") == "start-middle-end"); 153 1 : CATCH_REQUIRE(vars.get_variables().size() == 6); 154 : 155 1 : vars.set_variable("additive", "beg", advgetopt::assignment_t::ASSIGNMENT_APPEND); 156 1 : CATCH_REQUIRE(vars.get_variable("additive") == "beg"); 157 1 : CATCH_REQUIRE(vars.get_variables().size() == 7); 158 1 : vars.set_variable("additive", ":mid", advgetopt::assignment_t::ASSIGNMENT_APPEND); 159 1 : CATCH_REQUIRE(vars.get_variable("additive") == "beg:mid"); 160 1 : CATCH_REQUIRE(vars.get_variables().size() == 7); 161 1 : vars.set_variable("additive", ":end", advgetopt::assignment_t::ASSIGNMENT_APPEND); 162 1 : CATCH_REQUIRE(vars.get_variable("additive") == "beg:mid:end"); 163 1 : CATCH_REQUIRE(vars.get_variables().size() == 7); 164 1 : } 165 1 : CATCH_END_SECTION() 166 1 : } 167 : 168 : 169 4 : CATCH_TEST_CASE("invalid_variable_name", "[variables][invalid]") 170 : { 171 4 : CATCH_START_SECTION("invalid_variable_name: parsing an empty section name throws") 172 5 : CATCH_REQUIRE_THROWS_MATCHES( 173 : advgetopt::variables::canonicalize_variable_name(":bad_start") 174 : , advgetopt::getopt_invalid 175 : , Catch::Matchers::ExceptionMessage( 176 : "getopt_exception: found an empty section name in \":bad_start\".")); 177 4 : CATCH_END_SECTION() 178 : 179 4 : CATCH_START_SECTION("invalid_variable_name: parsing first section name that start with a digit fails") 180 5 : CATCH_REQUIRE_THROWS_MATCHES( 181 : advgetopt::variables::canonicalize_variable_name("3::bad_start") 182 : , advgetopt::getopt_invalid 183 : , Catch::Matchers::ExceptionMessage( 184 : "getopt_exception: a variable name or section name in \"3::bad_start\" starts with a digit, which is not allowed.")); 185 4 : CATCH_END_SECTION() 186 : 187 4 : CATCH_START_SECTION("invalid_variable_name: parsing second section name that start with a digit fails") 188 5 : CATCH_REQUIRE_THROWS_MATCHES( 189 : advgetopt::variables::canonicalize_variable_name("good::3::bad_section") 190 : , advgetopt::getopt_invalid 191 : , Catch::Matchers::ExceptionMessage( 192 : "getopt_exception: a variable name or section name in \"good::3::bad_section\" starts with a digit, which is not allowed.")); 193 4 : CATCH_END_SECTION() 194 : 195 4 : CATCH_START_SECTION("invalid_variable_name: parsing variable name that start with a digit fails") 196 5 : CATCH_REQUIRE_THROWS_MATCHES( 197 : advgetopt::variables::canonicalize_variable_name("good::and_bad::9times") 198 : , advgetopt::getopt_invalid 199 : , Catch::Matchers::ExceptionMessage( 200 : "getopt_exception: a variable name or section name in \"good::and_bad::9times\" starts with a digit, which is not allowed.")); 201 4 : CATCH_END_SECTION() 202 4 : } 203 : 204 : 205 1 : CATCH_TEST_CASE("invalid_variable", "[variables][invalid]") 206 : { 207 1 : CATCH_START_SECTION("invalid_variable: NEW assignment fails if variable exists") 208 : { 209 1 : advgetopt::variables vars; 210 : 211 1 : vars.set_variable("unique", "works", advgetopt::assignment_t::ASSIGNMENT_NEW); 212 1 : CATCH_REQUIRE(vars.get_variable("unique") == "works"); 213 1 : CATCH_REQUIRE(vars.get_variables().size() == 1); 214 : 215 9 : CATCH_REQUIRE_THROWS_MATCHES( 216 : vars.set_variable("unique", "fail", advgetopt::assignment_t::ASSIGNMENT_NEW) 217 : , advgetopt::getopt_defined_twice 218 : , Catch::Matchers::ExceptionMessage( 219 : "getopt_exception: variable \"unique\" is already defined.")); 220 1 : } 221 1 : CATCH_END_SECTION() 222 1 : } 223 : 224 : 225 : 226 : // vim: ts=4 sw=4 et