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