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