Line data Source code
1 : /*
2 : * License:
3 : * Copyright (c) 2006-2021 Made to Order Software Corp. All Rights Reserved
4 : *
5 : * https://snapwebsites.org/
6 : * contact@m2osw.com
7 : *
8 : * This program is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU General Public License as published by
10 : * the Free Software Foundation; either version 2 of the License, or
11 : * (at your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License along
19 : * with this program; if not, write to the Free Software Foundation, Inc.,
20 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 : *
22 : * Authors:
23 : * Alexis Wilke alexis@m2osw.com
24 : */
25 :
26 : // self
27 : //
28 : #include "main.h"
29 :
30 : // advgetopt lib
31 : //
32 : #include <advgetopt/exception.h>
33 :
34 : // snapdev lib
35 : //
36 : #include <snapdev/safe_setenv.h>
37 :
38 : // C++ lib
39 : //
40 : #include <fstream>
41 :
42 :
43 :
44 :
45 8 : CATCH_TEST_CASE("valid_options_files", "[options][valid][files]")
46 : {
47 12 : CATCH_START_SECTION("Check the default path with a nullptr (not a very good test, though)")
48 1 : advgetopt::option const options[] =
49 : {
50 : advgetopt::define_option(
51 : advgetopt::Name("verbose")
52 : , advgetopt::ShortName('v')
53 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
54 : , advgetopt::Help("a verbose like option, select it or not.")
55 : ),
56 : advgetopt::end_options()
57 : };
58 :
59 1 : advgetopt::options_environment options_env;
60 1 : options_env.f_project_name = "this-is-the-name-of-a-test-project-which-wont-ever-exist";
61 1 : options_env.f_options = options;
62 1 : options_env.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
63 1 : options_env.f_help_header = "Usage: test valid options from file";
64 :
65 1 : char const * sub_cargv[] =
66 : {
67 : "tests/unittests/no_file_to_load",
68 : "--verbose",
69 : nullptr
70 : };
71 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
72 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
73 :
74 2 : advgetopt::getopt opt(options_env, sub_argc, sub_argv);
75 :
76 : // check that the result is valid
77 :
78 : // an invalid parameter, MUST NOT EXIST
79 1 : CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
80 1 : CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
81 :
82 : // the valid parameter
83 1 : CATCH_REQUIRE(opt.is_defined("verbose"));
84 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
85 1 : CATCH_REQUIRE(opt.size("verbose") == 1);
86 :
87 : // other parameters
88 1 : CATCH_REQUIRE(opt.get_program_name() == "no_file_to_load");
89 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/no_file_to_load");
90 : CATCH_END_SECTION()
91 :
92 12 : CATCH_START_SECTION("Check the default path with an empty string (not a very good test, though)")
93 1 : advgetopt::option const options[] =
94 : {
95 : advgetopt::define_option(
96 : advgetopt::Name("verbose")
97 : , advgetopt::ShortName('v')
98 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
99 : , advgetopt::Help("a verbose like option, select it or not.")
100 : ),
101 : advgetopt::end_options()
102 : };
103 :
104 1 : advgetopt::options_environment options_env;
105 1 : options_env.f_project_name = "this-is-the-name-of-a-test-project-which-wont-ever-exist";
106 1 : options_env.f_options = options;
107 1 : options_env.f_options_files_directory = "";
108 1 : options_env.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
109 1 : options_env.f_help_header = "Usage: test valid options from file";
110 :
111 1 : char const * sub_cargv[] =
112 : {
113 : "tests/unittests/no_file_to_load",
114 : "--verbose",
115 : nullptr
116 : };
117 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
118 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
119 :
120 2 : advgetopt::getopt opt(options_env, sub_argc, sub_argv);
121 :
122 : // check that the result is valid
123 :
124 : // an invalid parameter, MUST NOT EXIST
125 1 : CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
126 1 : CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
127 :
128 : // the valid parameter
129 1 : CATCH_REQUIRE(opt.is_defined("verbose"));
130 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
131 1 : CATCH_REQUIRE(opt.size("verbose") == 1);
132 :
133 : // other parameters
134 1 : CATCH_REQUIRE(opt.get_program_name() == "no_file_to_load");
135 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/no_file_to_load");
136 : CATCH_END_SECTION()
137 :
138 12 : CATCH_START_SECTION("Check the parsing of a valid options.ini file")
139 : // create a file and make sure it's not read if the project name
140 : // is empty
141 : //
142 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
143 1 : tmpdir += "/shared/advgetopt";
144 2 : std::stringstream ss;
145 1 : ss << "mkdir -p " << tmpdir;
146 1 : if(system(ss.str().c_str()) != 0)
147 : {
148 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
149 0 : exit(1);
150 : }
151 2 : std::string const options_filename(tmpdir + "/no-project-name.ini");
152 :
153 1 : advgetopt::option const valid_options_from_file_list[] =
154 : {
155 : advgetopt::define_option(
156 : advgetopt::Name("verbose")
157 : , advgetopt::ShortName('v')
158 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
159 : , advgetopt::Help("a verbose like option, select it or not.")
160 : ),
161 : advgetopt::end_options()
162 : };
163 :
164 1 : advgetopt::options_environment valid_options_from_file;
165 1 : valid_options_from_file.f_project_name = nullptr;
166 1 : valid_options_from_file.f_options = valid_options_from_file_list;
167 1 : valid_options_from_file.f_options_files_directory = tmpdir.c_str();
168 1 : valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
169 1 : valid_options_from_file.f_help_header = "Usage: test valid options from file";
170 :
171 : {
172 2 : std::ofstream options_file;
173 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
174 1 : CATCH_REQUIRE(options_file.good());
175 1 : options_file <<
176 : "# Auto-generated\n"
177 :
178 : "[no-project-name]\n"
179 : "shortname=n\n"
180 : "default='inexistent'\n"
181 : "help=Testing that this doesn't get loaded\n"
182 : "allowed=command-line,environment-variable,configuration-file\n"
183 : ;
184 : }
185 :
186 1 : char const * sub_cargv[] =
187 : {
188 : "tests/unittests/file_not_loaded",
189 : "--verbose",
190 : nullptr
191 : };
192 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
193 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
194 :
195 2 : advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
196 :
197 : // check that the result is valid
198 :
199 : // an invalid parameter, MUST NOT EXIST
200 1 : CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
201 1 : CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
202 :
203 : // the valid parameter
204 1 : CATCH_REQUIRE(opt.is_defined("verbose"));
205 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
206 1 : CATCH_REQUIRE(opt.size("verbose") == 1);
207 :
208 : // "--no-project-name"
209 1 : CATCH_REQUIRE(opt.get_option("no-project-name") == nullptr);
210 1 : CATCH_REQUIRE_FALSE(opt.is_defined("no-project-name"));
211 :
212 : // other parameters
213 1 : CATCH_REQUIRE(opt.get_program_name() == "file_not_loaded");
214 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/file_not_loaded");
215 : CATCH_END_SECTION()
216 :
217 12 : CATCH_START_SECTION("Project name is an empty string")
218 : // create a file and make sure it's not read if the project name
219 : // is empty
220 : //
221 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
222 1 : tmpdir += "/shared/advgetopt";
223 2 : std::stringstream ss;
224 1 : ss << "mkdir -p " << tmpdir;
225 1 : if(system(ss.str().c_str()) != 0)
226 : {
227 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
228 0 : exit(1);
229 : }
230 2 : std::string const options_filename(tmpdir + "/empty-string.ini");
231 :
232 1 : advgetopt::option const valid_options_from_file_list[] =
233 : {
234 : advgetopt::define_option(
235 : advgetopt::Name("verbose")
236 : , advgetopt::ShortName('v')
237 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
238 : , advgetopt::Help("a verbose like option, select it or not.")
239 : ),
240 : advgetopt::end_options()
241 : };
242 :
243 1 : advgetopt::options_environment valid_options_from_file;
244 1 : valid_options_from_file.f_project_name = "";
245 1 : valid_options_from_file.f_options = valid_options_from_file_list;
246 1 : valid_options_from_file.f_options_files_directory = tmpdir.c_str();
247 1 : valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
248 1 : valid_options_from_file.f_help_header = "Usage: test valid options from file";
249 :
250 : {
251 2 : std::ofstream options_file;
252 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
253 1 : CATCH_REQUIRE(options_file.good());
254 1 : options_file <<
255 : "# Auto-generated\n"
256 :
257 : "[no-project-name]\n"
258 : "shortname=n\n"
259 : "default='inexistent'\n"
260 : "help=Testing that this doesn't get loaded\n"
261 : "allowed=command-line,environment-variable,configuration-file\n"
262 : ;
263 : }
264 :
265 1 : char const * sub_cargv[] =
266 : {
267 : "tests/unittests/file_not_loaded",
268 : "--verbose",
269 : nullptr
270 : };
271 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
272 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
273 :
274 2 : advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
275 :
276 : // check that the result is valid
277 :
278 : // an invalid parameter, MUST NOT EXIST
279 1 : CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
280 1 : CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
281 :
282 : // the valid parameter
283 1 : CATCH_REQUIRE(opt.is_defined("verbose"));
284 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
285 1 : CATCH_REQUIRE(opt.size("verbose") == 1);
286 :
287 : // "--no-project-name"
288 1 : CATCH_REQUIRE(opt.get_option("no-project-name") == nullptr);
289 1 : CATCH_REQUIRE_FALSE(opt.is_defined("no-project-name"));
290 :
291 : // other parameters
292 1 : CATCH_REQUIRE(opt.get_program_name() == "file_not_loaded");
293 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/file_not_loaded");
294 : CATCH_END_SECTION()
295 :
296 12 : CATCH_START_SECTION("Check the parsing of a valid options.ini file")
297 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
298 1 : tmpdir += "/shared/advgetopt";
299 2 : std::stringstream ss;
300 1 : ss << "mkdir -p " << tmpdir;
301 1 : if(system(ss.str().c_str()) != 0)
302 : {
303 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
304 0 : exit(1);
305 : }
306 2 : std::string const options_filename(tmpdir + "/unittest.ini");
307 :
308 1 : advgetopt::option const valid_options_from_file_list[] =
309 : {
310 : advgetopt::define_option(
311 : advgetopt::Name("verbose")
312 : , advgetopt::ShortName('v')
313 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
314 : , advgetopt::Help("a verbose like option, select it or not.")
315 : ),
316 : advgetopt::end_options()
317 : };
318 :
319 1 : advgetopt::options_environment valid_options_from_file;
320 1 : valid_options_from_file.f_project_name = "unittest";
321 1 : valid_options_from_file.f_options = valid_options_from_file_list;
322 1 : valid_options_from_file.f_options_files_directory = tmpdir.c_str();
323 1 : valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
324 1 : valid_options_from_file.f_help_header = "Usage: test valid options from file";
325 :
326 1 : snap::safe_setenv env("ADVGETOPT_TEST_OPTIONS"
327 : , "--verbose"
328 : " --more purple"
329 : " -f left.txt center.txt right.txt"
330 : " --size 519"
331 : " --from"
332 2 : " --output destination.txt");
333 :
334 : {
335 2 : std::ofstream options_file;
336 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
337 1 : CATCH_REQUIRE(options_file.good());
338 1 : options_file <<
339 : "# Auto-generated\n"
340 :
341 : "[more]\n"
342 : "shortname=m\n"
343 : "default='More Stuff'\n"
344 : "help=Allow for more stuff to be added\n"
345 : "validator=regex(\"purple|yellow|blue|red|green|orange|brown\")\n"
346 : "allowed=command-line,environment-variable,configuration-file\n"
347 : "show-usage-on-error\n"
348 : "required\n"
349 :
350 : "[size]\n"
351 : "shortname=s\n"
352 : "help=Specify the size\n"
353 : "validator=/[0-9]+/\n"
354 : "allowed=environment-variable,configuration-file\n"
355 : "default=31\n"
356 : "required\n"
357 :
358 : "[files]\n"
359 : "shortname=f\n"
360 : "help=List of file names\n"
361 : "validator=/.*\\.txt/i\n"
362 : "allowed=command-line,environment-variable\n"
363 : "multiple\n"
364 : "required\n"
365 :
366 : "[from]\n"
367 : "shortname=F\n"
368 : "help=Request for the geographcal location representing the origin of the files; optionally you can specify the format\n"
369 : "validator=integer\n"
370 : "allowed=command-line,environment-variable,configuration-file\n"
371 :
372 : "[output]\n"
373 : "shortname=o\n"
374 : "default=a.out\n"
375 : "help=output file\n"
376 : "allowed=environment-variable\n"
377 : "required\n"
378 :
379 : "[license]\n"
380 : "shortname=l\n"
381 : "help=show this test license\n"
382 : "allowed=command-line\n"
383 : "no-arguments\n"
384 :
385 : "[licence]\n"
386 : "alias=license\n"
387 : "allowed=command-line\n"
388 : "no-arguments\n"
389 : ;
390 : }
391 :
392 1 : char const * sub_cargv[] =
393 : {
394 : "tests/unittests/valid_options_files",
395 : "--verbose",
396 : "--licence",
397 : nullptr
398 : };
399 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
400 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
401 :
402 2 : advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
403 :
404 : // check that the result is valid
405 :
406 : // an invalid parameter, MUST NOT EXIST
407 1 : CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
408 1 : CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
409 :
410 : // the valid parameter
411 1 : CATCH_REQUIRE(opt.is_defined("verbose"));
412 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
413 1 : CATCH_REQUIRE(opt.size("verbose") == 1);
414 :
415 : // "--more"
416 1 : CATCH_REQUIRE(opt.is_defined("more"));
417 1 : CATCH_REQUIRE(opt.get_string("more") == "purple");
418 1 : CATCH_REQUIRE(opt.get_default("more") == "More Stuff");
419 1 : CATCH_REQUIRE(opt.size("more") == 1);
420 :
421 : // "--size <value>"
422 1 : CATCH_REQUIRE(opt.is_defined("size"));
423 1 : CATCH_REQUIRE(opt.get_string("size") == "519");
424 1 : CATCH_REQUIRE(opt.get_string("size", 0) == "519");
425 1 : CATCH_REQUIRE(opt.get_default("size") == "31");
426 1 : CATCH_REQUIRE(opt.size("size") == 1);
427 1 : CATCH_REQUIRE(opt.get_long("size") == 519);
428 :
429 : // "--files"
430 1 : CATCH_REQUIRE(opt.is_defined("files"));
431 1 : CATCH_REQUIRE(opt.get_string("files") == "left.txt");
432 1 : CATCH_REQUIRE(opt.get_string("files", 0) == "left.txt");
433 1 : CATCH_REQUIRE(opt.get_string("files", 1) == "center.txt");
434 1 : CATCH_REQUIRE(opt.get_string("files", 2) == "right.txt");
435 1 : CATCH_REQUIRE(opt.get_default("files").empty());
436 1 : CATCH_REQUIRE(opt.size("files") == 3);
437 :
438 : // "--from"
439 1 : CATCH_REQUIRE(opt.is_defined("from"));
440 1 : CATCH_REQUIRE(opt.size("from") == 1);
441 1 : CATCH_REQUIRE(opt.get_string("from") == "");
442 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
443 1 : CATCH_REQUIRE(opt.get_long("from") == -1);
444 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
445 1 : CATCH_REQUIRE(opt.get_default("from").empty());
446 :
447 : // "--output"
448 1 : CATCH_REQUIRE(opt.is_defined("output"));
449 1 : CATCH_REQUIRE(opt.get_string("output") == "destination.txt"); // same as index = 0
450 1 : CATCH_REQUIRE(opt.get_string("output", 0) == "destination.txt");
451 1 : CATCH_REQUIRE(opt.get_default("output") == "a.out");
452 1 : CATCH_REQUIRE(opt.size("output") == 1);
453 :
454 : // "--from"
455 1 : CATCH_REQUIRE(opt.is_defined("license"));
456 1 : CATCH_REQUIRE(opt.get_string("license") == "");
457 1 : CATCH_REQUIRE(opt.get_default("license").empty());
458 1 : CATCH_REQUIRE(opt.size("license") == 1);
459 :
460 : // other parameters
461 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
462 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
463 :
464 1 : char const * sub_cargv2[] =
465 : {
466 : "this/is/ignored",
467 : "--from",
468 : "1001",
469 : nullptr
470 : };
471 1 : int const sub_argc2(sizeof(sub_cargv2) / sizeof(sub_cargv2[0]) - 1);
472 1 : char ** sub_argv2 = const_cast<char **>(sub_cargv2);
473 :
474 1 : opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
475 :
476 : // "--from"
477 1 : CATCH_REQUIRE(opt.is_defined("from"));
478 1 : CATCH_REQUIRE(opt.size("from") == 1);
479 1 : CATCH_REQUIRE(opt.get_string("from") == "1001");
480 1 : CATCH_REQUIRE(opt.get_long("from") == 1001);
481 1 : CATCH_REQUIRE(opt.get_default("from").empty());
482 :
483 : // other parameters
484 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
485 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
486 :
487 : // keep the last value...
488 : //
489 1 : opt.parse_environment_variable();
490 :
491 : // "--from"
492 1 : CATCH_REQUIRE(opt.is_defined("from"));
493 1 : CATCH_REQUIRE(opt.size("from") == 1);
494 1 : CATCH_REQUIRE(opt.get_string("from") == "");
495 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
496 1 : CATCH_REQUIRE(opt.get_long("from") == -1);
497 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
498 1 : CATCH_REQUIRE(opt.get_default("from").empty());
499 :
500 : // other parameters
501 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
502 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
503 :
504 : // a reset will restore the state
505 : //
506 1 : opt.reset();
507 :
508 : // the valid parameter
509 1 : CATCH_REQUIRE_FALSE(opt.is_defined("verbose"));
510 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
511 1 : CATCH_REQUIRE(opt.size("verbose") == 0);
512 :
513 : // "--from"
514 1 : CATCH_REQUIRE_FALSE(opt.is_defined("from"));
515 1 : CATCH_REQUIRE(opt.get_default("from").empty());
516 1 : CATCH_REQUIRE(opt.size("from") == 0);
517 :
518 1 : opt.parse_environment_variable();
519 1 : opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
520 :
521 : // "--from"
522 1 : CATCH_REQUIRE(opt.is_defined("from"));
523 1 : CATCH_REQUIRE(opt.get_string("from") == "1001");
524 1 : CATCH_REQUIRE(opt.get_long("from") == 1001);
525 1 : CATCH_REQUIRE(opt.get_default("from").empty());
526 1 : CATCH_REQUIRE(opt.size("from") == 1);
527 :
528 : // other parameters
529 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
530 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
531 :
532 :
533 : // test that the validators do work here (i.e. generate errors as
534 : // expected when we use the wrong options.)
535 : //
536 : {
537 1 : snap::safe_setenv subenv("ADVGETOPT_TEST_OPTIONS"
538 : , "--verbose"
539 : " --size '1001 meters'"
540 : " -f valid.cpp"
541 : " --from auto-build"
542 2 : " --more black");
543 :
544 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"1001 meters\" given to parameter --size is not considered valid.");
545 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"valid.cpp\" given to parameter --files is not considered valid.");
546 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"auto-build\" given to parameter --from is not considered valid.");
547 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"black\" given to parameter --more is not considered valid.");
548 1 : opt.parse_environment_variable();
549 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
550 : }
551 : CATCH_END_SECTION()
552 :
553 12 : CATCH_START_SECTION("Check with validators in the definition")
554 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
555 1 : tmpdir += "/shared/advgetopt-validators-in-table";
556 2 : std::stringstream ss;
557 1 : ss << "mkdir -p " << tmpdir;
558 1 : if(system(ss.str().c_str()) != 0)
559 : {
560 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
561 0 : exit(1);
562 : }
563 2 : std::string const options_filename(tmpdir + "/unittest.ini");
564 :
565 1 : advgetopt::option const valid_options_from_file_list[] =
566 : {
567 : advgetopt::define_option(
568 : advgetopt::Name("verbose")
569 : , advgetopt::ShortName('v')
570 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
571 : , advgetopt::Help("a verbose like option, select it or not.")
572 : ),
573 : advgetopt::define_option(
574 : advgetopt::Name("size")
575 : , advgetopt::ShortName('s')
576 : , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED>())
577 : , advgetopt::Help("Specify the size.")
578 : , advgetopt::Validator("integer(0...100)")
579 : , advgetopt::DefaultValue("31")
580 : ),
581 : advgetopt::define_option(
582 : advgetopt::Name("files")
583 : , advgetopt::ShortName('f')
584 : , advgetopt::Help("List of file names")
585 : , advgetopt::Validator("/.*\\.txt/i")
586 : , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED, advgetopt::GETOPT_FLAG_MULTIPLE>())
587 : ),
588 : advgetopt::define_option(
589 : advgetopt::Name("from")
590 : , advgetopt::ShortName('F')
591 : , advgetopt::Help("Request for the geographcal location representing the origin of the files; optionally you can specify the format")
592 : , advgetopt::Validator("integer")
593 : , advgetopt::Flags(advgetopt::all_flags<>())
594 : ),
595 : advgetopt::define_option(
596 : advgetopt::Name("more")
597 : , advgetopt::ShortName('m')
598 : , advgetopt::Help("Allow for more stuff to be added")
599 : , advgetopt::Validator("regex(\"purple|yellow|blue|red|green|orange|brown\")")
600 : , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED, advgetopt::GETOPT_FLAG_SHOW_USAGE_ON_ERROR>())
601 : , advgetopt::DefaultValue("More Stuff")
602 : ),
603 : advgetopt::end_options()
604 : };
605 :
606 1 : advgetopt::options_environment valid_options_from_file;
607 1 : valid_options_from_file.f_project_name = "unittest";
608 1 : valid_options_from_file.f_options = valid_options_from_file_list;
609 1 : valid_options_from_file.f_options_files_directory = tmpdir.c_str();
610 1 : valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
611 1 : valid_options_from_file.f_help_header = "Usage: test valid options from file";
612 :
613 1 : snap::safe_setenv env("ADVGETOPT_TEST_OPTIONS"
614 : , "--verbose"
615 : " --more purple"
616 : " -f left.txt center.txt right.txt"
617 : " --size 19"
618 : " --from"
619 2 : " --output destination.txt");
620 :
621 : {
622 2 : std::ofstream options_file;
623 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
624 1 : CATCH_REQUIRE(options_file.good());
625 1 : options_file <<
626 : "# Auto-generated\n"
627 :
628 : "[output]\n"
629 : "shortname=o\n"
630 : "default=a.out\n"
631 : "help=output file\n"
632 : "allowed=environment-variable\n"
633 : "required\n"
634 :
635 : "[license]\n"
636 : "shortname=l\n"
637 : "help=show this test license\n"
638 : "allowed=command-line\n"
639 : "no-arguments\n"
640 :
641 : "[licence]\n"
642 : "alias=license\n"
643 : "allowed=command-line\n"
644 : "no-arguments\n"
645 : ;
646 : }
647 :
648 1 : char const * sub_cargv[] =
649 : {
650 : "tests/unittests/valid_options_files",
651 : "--verbose",
652 : "--licence",
653 : nullptr
654 : };
655 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
656 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
657 :
658 2 : advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
659 :
660 : // check that the result is valid
661 :
662 : // an invalid parameter, MUST NOT EXIST
663 1 : CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
664 1 : CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
665 :
666 : // the valid parameter
667 1 : CATCH_REQUIRE(opt.is_defined("verbose"));
668 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
669 1 : CATCH_REQUIRE(opt.size("verbose") == 1);
670 :
671 : // "--more"
672 1 : CATCH_REQUIRE(opt.is_defined("more"));
673 1 : CATCH_REQUIRE(opt.get_string("more") == "purple");
674 1 : CATCH_REQUIRE(opt.get_default("more") == "More Stuff");
675 1 : CATCH_REQUIRE(opt.size("more") == 1);
676 :
677 : // "--size <value>"
678 1 : CATCH_REQUIRE(opt.is_defined("size"));
679 1 : CATCH_REQUIRE(opt.get_string("size") == "19");
680 1 : CATCH_REQUIRE(opt.get_string("size", 0) == "19");
681 1 : CATCH_REQUIRE(opt.get_default("size") == "31");
682 1 : CATCH_REQUIRE(opt.size("size") == 1);
683 1 : CATCH_REQUIRE(opt.get_long("size") == 19);
684 :
685 : // "--files"
686 1 : CATCH_REQUIRE(opt.is_defined("files"));
687 1 : CATCH_REQUIRE(opt.get_string("files") == "left.txt");
688 1 : CATCH_REQUIRE(opt.get_string("files", 0) == "left.txt");
689 1 : CATCH_REQUIRE(opt.get_string("files", 1) == "center.txt");
690 1 : CATCH_REQUIRE(opt.get_string("files", 2) == "right.txt");
691 1 : CATCH_REQUIRE(opt.get_default("files").empty());
692 1 : CATCH_REQUIRE(opt.size("files") == 3);
693 :
694 : // "--from"
695 1 : CATCH_REQUIRE(opt.is_defined("from"));
696 1 : CATCH_REQUIRE(opt.size("from") == 1);
697 1 : CATCH_REQUIRE(opt.get_string("from") == "");
698 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
699 1 : CATCH_REQUIRE(opt.get_long("from") == -1);
700 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
701 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
702 1 : CATCH_REQUIRE(opt.get_long("from") == -1);
703 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
704 1 : CATCH_REQUIRE(opt.get_default("from").empty());
705 :
706 : // "--output"
707 1 : CATCH_REQUIRE(opt.is_defined("output"));
708 1 : CATCH_REQUIRE(opt.get_string("output") == "destination.txt"); // same as index = 0
709 1 : CATCH_REQUIRE(opt.get_string("output", 0) == "destination.txt");
710 1 : CATCH_REQUIRE(opt.get_default("output") == "a.out");
711 1 : CATCH_REQUIRE(opt.size("output") == 1);
712 :
713 : // "--from"
714 1 : CATCH_REQUIRE(opt.is_defined("license"));
715 1 : CATCH_REQUIRE(opt.get_string("license") == "");
716 1 : CATCH_REQUIRE(opt.get_default("license").empty());
717 1 : CATCH_REQUIRE(opt.size("license") == 1);
718 :
719 : // other parameters
720 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
721 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
722 :
723 1 : char const * sub_cargv2[] =
724 : {
725 : "this/is/ignored",
726 : "--from",
727 : "1001",
728 : nullptr
729 : };
730 1 : int const sub_argc2(sizeof(sub_cargv2) / sizeof(sub_cargv2[0]) - 1);
731 1 : char ** sub_argv2 = const_cast<char **>(sub_cargv2);
732 :
733 1 : opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
734 :
735 : // "--from"
736 1 : CATCH_REQUIRE(opt.is_defined("from"));
737 1 : CATCH_REQUIRE(opt.size("from") == 1);
738 1 : CATCH_REQUIRE(opt.get_string("from") == "1001");
739 1 : CATCH_REQUIRE(opt.get_long("from") == 1001);
740 1 : CATCH_REQUIRE(opt.get_default("from").empty());
741 :
742 : // other parameters
743 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
744 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
745 :
746 : // keep the last value...
747 : //
748 1 : opt.parse_environment_variable();
749 :
750 : // "--from"
751 1 : CATCH_REQUIRE(opt.is_defined("from"));
752 1 : CATCH_REQUIRE(opt.size("from") == 1);
753 1 : CATCH_REQUIRE(opt.get_string("from") == "");
754 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
755 1 : CATCH_REQUIRE(opt.get_long("from") == -1);
756 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
757 1 : CATCH_REQUIRE(opt.get_default("from").empty());
758 :
759 : // other parameters
760 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
761 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
762 :
763 : // a reset will restore the state
764 : //
765 1 : opt.reset();
766 :
767 : // the valid parameter
768 1 : CATCH_REQUIRE_FALSE(opt.is_defined("verbose"));
769 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
770 1 : CATCH_REQUIRE(opt.size("verbose") == 0);
771 :
772 : // "--from"
773 1 : CATCH_REQUIRE_FALSE(opt.is_defined("from"));
774 1 : CATCH_REQUIRE(opt.get_default("from").empty());
775 1 : CATCH_REQUIRE(opt.size("from") == 0);
776 :
777 1 : opt.parse_environment_variable();
778 1 : opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
779 :
780 : // "--from"
781 1 : CATCH_REQUIRE(opt.is_defined("from"));
782 1 : CATCH_REQUIRE(opt.get_string("from") == "1001");
783 1 : CATCH_REQUIRE(opt.get_long("from") == 1001);
784 1 : CATCH_REQUIRE(opt.get_default("from").empty());
785 1 : CATCH_REQUIRE(opt.size("from") == 1);
786 :
787 : // other parameters
788 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
789 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
790 :
791 : // test that the validators do work here (i.e. generate errors as
792 : // expected when we use the wrong options.)
793 : //
794 1 : char const * sub_cargv3[] =
795 : {
796 : "this/is/ignored",
797 : "--size",
798 : "1001",
799 : "-f",
800 : "valid.cpp",
801 : "--from",
802 : "51",
803 : "--more",
804 : "black",
805 : nullptr
806 : };
807 1 : int const sub_argc3(sizeof(sub_cargv3) / sizeof(sub_cargv3[0]) - 1);
808 1 : char ** sub_argv3 = const_cast<char **>(sub_cargv3);
809 :
810 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"1001\" given to parameter --size is not considered valid.");
811 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"valid.cpp\" given to parameter --files is not considered valid.");
812 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"black\" given to parameter --more is not considered valid.");
813 1 : opt.parse_arguments(sub_argc3, sub_argv3, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
814 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
815 : CATCH_END_SECTION()
816 6 : }
817 :
818 :
819 9 : CATCH_TEST_CASE("invalid_options_files", "[options][invalid][files]")
820 : {
821 14 : CATCH_START_SECTION("2+ section names")
822 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
823 1 : tmpdir += "/shared/advgetopt";
824 2 : std::stringstream ss;
825 1 : ss << "mkdir -p " << tmpdir;
826 1 : if(system(ss.str().c_str()) != 0)
827 : {
828 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
829 0 : exit(1);
830 : }
831 2 : std::string const options_filename(tmpdir + "/bad-section.ini");
832 :
833 1 : advgetopt::option const options[] =
834 : {
835 : advgetopt::define_option(
836 : advgetopt::Name("verbose")
837 : , advgetopt::ShortName('v')
838 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
839 : , advgetopt::Help("a verbose like option, select it or not.")
840 : ),
841 : advgetopt::end_options()
842 : };
843 :
844 1 : advgetopt::options_environment options_environment;
845 1 : options_environment.f_project_name = "bad-section";
846 1 : options_environment.f_options = options;
847 1 : options_environment.f_options_files_directory = tmpdir.c_str();
848 1 : options_environment.f_environment_variable_name = nullptr;
849 1 : options_environment.f_help_header = "Usage: test invalid section name";
850 :
851 : {
852 2 : std::ofstream options_file;
853 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
854 1 : CATCH_REQUIRE(options_file.good());
855 1 : options_file <<
856 : "# Auto-generated\n"
857 :
858 : "[invalid::name]\n"
859 : "shortname=m\n"
860 : "default='Invalid Stuff'\n"
861 : "help=Testing that a section name can't include \"::\"\n"
862 : "allowed=command-line,environment-variable,configuration-file\n"
863 : ;
864 : }
865 :
866 1 : char const * sub_cargv[] =
867 : {
868 : "tests/unittests/invalid_name_in_options_ini",
869 : "--verbose",
870 : nullptr
871 : };
872 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
873 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
874 :
875 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
876 : "error: option name \"shortname\" cannot be added to"
877 : " section \"invalid::name\" because this"
878 : " configuration only accepts one section level.");
879 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
880 : "error: option name \"default\" cannot be added to"
881 : " section \"invalid::name\" because this"
882 : " configuration only accepts one section level.");
883 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
884 : "error: option name \"help\" cannot be added to"
885 : " section \"invalid::name\" because this"
886 : " configuration only accepts one section level.");
887 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
888 : "error: option name \"allowed\" cannot be added to"
889 : " section \"invalid::name\" because this"
890 : " configuration only accepts one section level.");
891 2 : advgetopt::getopt::pointer_t opt(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv));
892 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
893 :
894 1 : CATCH_REQUIRE(opt->size("invalid::name::shortname") == 0);
895 1 : CATCH_REQUIRE(opt->size("shortname") == 0);
896 : CATCH_END_SECTION()
897 :
898 14 : CATCH_START_SECTION("short name too long")
899 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
900 1 : tmpdir += "/shared/advgetopt";
901 2 : std::stringstream ss;
902 1 : ss << "mkdir -p " << tmpdir;
903 1 : if(system(ss.str().c_str()) != 0)
904 : {
905 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
906 0 : exit(1);
907 : }
908 2 : std::string const options_filename(tmpdir + "/bad-shortname.ini");
909 :
910 1 : advgetopt::option const options[] =
911 : {
912 : advgetopt::define_option(
913 : advgetopt::Name("verbose")
914 : , advgetopt::ShortName('v')
915 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
916 : , advgetopt::Help("a verbose like option, select it or not.")
917 : ),
918 : advgetopt::end_options()
919 : };
920 :
921 1 : advgetopt::options_environment options_environment;
922 1 : options_environment.f_project_name = "bad-shortname";
923 1 : options_environment.f_options = options;
924 1 : options_environment.f_options_files_directory = tmpdir.c_str();
925 1 : options_environment.f_environment_variable_name = nullptr;
926 1 : options_environment.f_help_header = "Usage: test invalid shortname";
927 :
928 : {
929 2 : std::ofstream options_file;
930 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
931 1 : CATCH_REQUIRE(options_file.good());
932 1 : options_file <<
933 : "# Auto-generated\n"
934 :
935 : "[badname]\n"
936 : "shortname=to\n"
937 : "default='Invalid Stuff'\n"
938 : "help=Testing that a shotname can't be 2 characters or more\n"
939 : "allowed=command-line,environment-variable,configuration-file\n"
940 : ;
941 : }
942 :
943 1 : char const * sub_cargv[] =
944 : {
945 : "tests/unittests/invalid_name_in_options_ini",
946 : "--verbose",
947 : nullptr
948 : };
949 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
950 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
951 :
952 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
953 : , advgetopt::getopt_logic_error
954 : , Catch::Matchers::ExceptionMessage(
955 : "getopt_logic_error: option \"badname\" has an invalid short name in \""
956 : + options_filename
957 : + "\", it can't be more than one character."));
958 : CATCH_END_SECTION()
959 :
960 14 : CATCH_START_SECTION("missing ')' in validator specification")
961 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
962 1 : tmpdir += "/shared/advgetopt";
963 2 : std::stringstream ss;
964 1 : ss << "mkdir -p " << tmpdir;
965 1 : if(system(ss.str().c_str()) != 0)
966 : {
967 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
968 0 : exit(1);
969 : }
970 2 : std::string const options_filename(tmpdir + "/bad-validator-parenthesis.ini");
971 :
972 1 : advgetopt::option const options[] =
973 : {
974 : advgetopt::define_option(
975 : advgetopt::Name("verbose")
976 : , advgetopt::ShortName('v')
977 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
978 : , advgetopt::Help("a verbose like option, select it or not.")
979 : ),
980 : advgetopt::end_options()
981 : };
982 :
983 1 : advgetopt::options_environment options_environment;
984 1 : options_environment.f_project_name = "bad-validator-parenthesis";
985 1 : options_environment.f_options = options;
986 1 : options_environment.f_options_files_directory = tmpdir.c_str();
987 1 : options_environment.f_environment_variable_name = nullptr;
988 1 : options_environment.f_help_header = "Usage: test invalid validator specification";
989 :
990 : {
991 2 : std::ofstream options_file;
992 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
993 1 : CATCH_REQUIRE(options_file.good());
994 1 : options_file <<
995 : "# Auto-generated\n"
996 :
997 : "[bad-validator]\n"
998 : "shortname=b\n"
999 : "default='Invalid Stuff'\n"
1000 : "help=Testing that a validator with parenthesis must have the ')'\n"
1001 : "validator=regex(\"missing ')'\"\n"
1002 : "allowed=command-line,environment-variable,configuration-file\n"
1003 : ;
1004 : }
1005 :
1006 1 : char const * sub_cargv[] =
1007 : {
1008 : "tests/unittests/invalid_validator_specification",
1009 : "--verbose",
1010 : nullptr
1011 : };
1012 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1013 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1014 :
1015 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1016 : , advgetopt::getopt_logic_error
1017 : , Catch::Matchers::ExceptionMessage(
1018 : "getopt_logic_error: invalid validator parameter definition: \"regex(\"missing ')'\"\", the ')' is missing."));
1019 : CATCH_END_SECTION()
1020 :
1021 14 : CATCH_START_SECTION("alias with help")
1022 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
1023 1 : tmpdir += "/shared/advgetopt";
1024 2 : std::stringstream ss;
1025 1 : ss << "mkdir -p " << tmpdir;
1026 1 : if(system(ss.str().c_str()) != 0)
1027 : {
1028 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1029 0 : exit(1);
1030 : }
1031 2 : std::string const options_filename(tmpdir + "/alias-with-help.ini");
1032 :
1033 1 : advgetopt::option const options[] =
1034 : {
1035 : advgetopt::define_option(
1036 : advgetopt::Name("verbose")
1037 : , advgetopt::ShortName('v')
1038 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1039 : , advgetopt::Help("a verbose like option, select it or not.")
1040 : ),
1041 : advgetopt::end_options()
1042 : };
1043 :
1044 1 : advgetopt::options_environment options_environment;
1045 1 : options_environment.f_project_name = "alias-with-help";
1046 1 : options_environment.f_options = options;
1047 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1048 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1049 1 : options_environment.f_environment_variable_name = nullptr;
1050 1 : options_environment.f_help_header = "Usage: test invalid validator specification";
1051 :
1052 : {
1053 2 : std::ofstream options_file;
1054 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1055 1 : CATCH_REQUIRE(options_file.good());
1056 1 : options_file <<
1057 : "# Auto-generated\n"
1058 :
1059 : "[licence]\n"
1060 : "shortname=l\n"
1061 : "default='Invalid Stuff'\n"
1062 : "alias=license\n"
1063 : "help=Testing that an alias can't accept a help string\n"
1064 : "allowed=command-line,environment-variable,configuration-file\n"
1065 : ;
1066 : }
1067 :
1068 1 : char const * sub_cargv[] =
1069 : {
1070 : "tests/unittests/invalid_alias_specification",
1071 : "--verbose",
1072 : nullptr
1073 : };
1074 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1075 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1076 :
1077 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1078 : , advgetopt::getopt_logic_error
1079 : , Catch::Matchers::ExceptionMessage(
1080 : "getopt_logic_error: option \"licence\" is an alias and as such it can't include a help=... parameter in \""
1081 : + options_filename
1082 : + "\"."));
1083 : CATCH_END_SECTION()
1084 :
1085 14 : CATCH_START_SECTION("no-name alias")
1086 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
1087 1 : tmpdir += "/shared/advgetopt";
1088 2 : std::stringstream ss;
1089 1 : ss << "mkdir -p " << tmpdir;
1090 1 : if(system(ss.str().c_str()) != 0)
1091 : {
1092 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1093 0 : exit(1);
1094 : }
1095 2 : std::string const options_filename(tmpdir + "/no-name-alias.ini");
1096 :
1097 1 : advgetopt::option const options[] =
1098 : {
1099 : advgetopt::define_option(
1100 : advgetopt::Name("verbose")
1101 : , advgetopt::ShortName('v')
1102 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1103 : , advgetopt::Help("a verbose like option, select it or not.")
1104 : ),
1105 : advgetopt::end_options()
1106 : };
1107 :
1108 1 : advgetopt::options_environment options_environment;
1109 1 : options_environment.f_project_name = "no-name-alias";
1110 1 : options_environment.f_options = options;
1111 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1112 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1113 1 : options_environment.f_environment_variable_name = nullptr;
1114 1 : options_environment.f_help_header = "Usage: test alias with no name specified";
1115 :
1116 : {
1117 2 : std::ofstream options_file;
1118 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1119 1 : CATCH_REQUIRE(options_file.good());
1120 1 : options_file <<
1121 : "# Auto-generated\n"
1122 :
1123 : "[foo]\n"
1124 : "shortname=f\n"
1125 : "default='Invalid Stuff'\n"
1126 : "alias=\n" // name missing (with an equal)
1127 : "allowed=command-line\n"
1128 : ;
1129 : }
1130 :
1131 1 : char const * sub_cargv[] =
1132 : {
1133 : "tests/unittests/non_existant_alias",
1134 : "--verbose",
1135 : nullptr
1136 : };
1137 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1138 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1139 :
1140 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1141 : , advgetopt::getopt_logic_error
1142 : , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
1143 : CATCH_END_SECTION()
1144 :
1145 14 : CATCH_START_SECTION("no-name alias v2")
1146 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
1147 1 : tmpdir += "/shared/advgetopt";
1148 2 : std::stringstream ss;
1149 1 : ss << "mkdir -p " << tmpdir;
1150 1 : if(system(ss.str().c_str()) != 0)
1151 : {
1152 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1153 0 : exit(1);
1154 : }
1155 2 : std::string const options_filename(tmpdir + "/no-name-alias-v2.ini");
1156 :
1157 1 : advgetopt::option const options[] =
1158 : {
1159 : advgetopt::define_option(
1160 : advgetopt::Name("verbose")
1161 : , advgetopt::ShortName('v')
1162 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1163 : , advgetopt::Help("a verbose like option, select it or not.")
1164 : ),
1165 : advgetopt::end_options()
1166 : };
1167 :
1168 1 : advgetopt::options_environment options_environment;
1169 1 : options_environment.f_project_name = "no-name-alias-v2";
1170 1 : options_environment.f_options = options;
1171 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1172 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1173 1 : options_environment.f_environment_variable_name = nullptr;
1174 1 : options_environment.f_help_header = "Usage: test alias with no name specified";
1175 :
1176 : {
1177 2 : std::ofstream options_file;
1178 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1179 1 : CATCH_REQUIRE(options_file.good());
1180 1 : options_file <<
1181 : "# Auto-generated\n"
1182 :
1183 : "[foo]\n"
1184 : "shortname=f\n"
1185 : "default='Invalid Stuff'\n"
1186 : "alias\n" // name missing (no equal)
1187 : "allowed=command-line\n"
1188 : ;
1189 : }
1190 :
1191 1 : char const * sub_cargv[] =
1192 : {
1193 : "tests/unittests/non_existant_alias",
1194 : "--verbose",
1195 : nullptr
1196 : };
1197 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1198 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1199 :
1200 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1201 : , advgetopt::getopt_logic_error
1202 : , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
1203 : CATCH_END_SECTION()
1204 :
1205 14 : CATCH_START_SECTION("non-existant alias")
1206 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
1207 1 : tmpdir += "/shared/advgetopt";
1208 2 : std::stringstream ss;
1209 1 : ss << "mkdir -p " << tmpdir;
1210 1 : if(system(ss.str().c_str()) != 0)
1211 : {
1212 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1213 0 : exit(1);
1214 : }
1215 2 : std::string const options_filename(tmpdir + "/non-existant-alias.ini");
1216 :
1217 1 : advgetopt::option const options[] =
1218 : {
1219 : advgetopt::define_option(
1220 : advgetopt::Name("verbose")
1221 : , advgetopt::ShortName('v')
1222 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1223 : , advgetopt::Help("a verbose like option, select it or not.")
1224 : ),
1225 : advgetopt::end_options()
1226 : };
1227 :
1228 1 : advgetopt::options_environment options_environment;
1229 1 : options_environment.f_project_name = "non-existant-alias";
1230 1 : options_environment.f_options = options;
1231 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1232 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1233 1 : options_environment.f_environment_variable_name = nullptr;
1234 1 : options_environment.f_help_header = "Usage: test invalid validator specification";
1235 :
1236 : {
1237 2 : std::ofstream options_file;
1238 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1239 1 : CATCH_REQUIRE(options_file.good());
1240 1 : options_file <<
1241 : "# Auto-generated\n"
1242 :
1243 : "[foo]\n"
1244 : "shortname=f\n"
1245 : "default='Invalid Stuff'\n"
1246 : "alias=bar\n" // option "bar" missing
1247 : "allowed=command-line\n"
1248 : ;
1249 : }
1250 :
1251 1 : char const * sub_cargv[] =
1252 : {
1253 : "tests/unittests/non_existant_alias",
1254 : "--verbose",
1255 : nullptr
1256 : };
1257 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1258 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1259 :
1260 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1261 : , advgetopt::getopt_logic_error
1262 : , Catch::Matchers::ExceptionMessage("getopt_logic_error: no option named \"bar\" to satisfy the alias of \"foo\"."));
1263 : CATCH_END_SECTION()
1264 13 : }
1265 :
1266 :
1267 :
1268 :
1269 :
1270 :
1271 :
1272 :
1273 :
1274 : // vim: ts=4 sw=4 et
|