Line data Source code
1 : // Copyright (c) 2006-2021 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 : snap::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 : snap::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 : snap::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, sub_argc, sub_argv));
894 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
895 :
896 1 : CATCH_REQUIRE(opt->size("invalid::name::shortname") == 0);
897 1 : CATCH_REQUIRE(opt->size("shortname") == 0);
898 : CATCH_END_SECTION()
899 :
900 14 : CATCH_START_SECTION("short name too long")
901 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
902 1 : tmpdir += "/shared/advgetopt";
903 2 : std::stringstream ss;
904 1 : ss << "mkdir -p " << tmpdir;
905 1 : if(system(ss.str().c_str()) != 0)
906 : {
907 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
908 0 : exit(1);
909 : }
910 2 : std::string const options_filename(tmpdir + "/bad-shortname.ini");
911 :
912 1 : advgetopt::option const options[] =
913 : {
914 : advgetopt::define_option(
915 : advgetopt::Name("verbose")
916 : , advgetopt::ShortName('v')
917 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
918 : , advgetopt::Help("a verbose like option, select it or not.")
919 : ),
920 : advgetopt::end_options()
921 : };
922 :
923 1 : advgetopt::options_environment options_environment;
924 1 : options_environment.f_project_name = "bad-shortname";
925 1 : options_environment.f_options = options;
926 1 : options_environment.f_options_files_directory = tmpdir.c_str();
927 1 : options_environment.f_environment_variable_name = nullptr;
928 1 : options_environment.f_help_header = "Usage: test invalid shortname";
929 :
930 : {
931 2 : std::ofstream options_file;
932 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
933 1 : CATCH_REQUIRE(options_file.good());
934 1 : options_file <<
935 : "# Auto-generated\n"
936 :
937 : "[badname]\n"
938 : "shortname=to\n"
939 : "default='Invalid Stuff'\n"
940 : "help=Testing that a shotname can't be 2 characters or more\n"
941 : "allowed=command-line,environment-variable,configuration-file\n"
942 : ;
943 : }
944 :
945 1 : char const * sub_cargv[] =
946 : {
947 : "tests/unittests/invalid_name_in_options_ini",
948 : "--verbose",
949 : nullptr
950 : };
951 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
952 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
953 :
954 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
955 : , advgetopt::getopt_logic_error
956 : , Catch::Matchers::ExceptionMessage(
957 : "getopt_logic_error: option \"badname\" has an invalid short name in \""
958 : + options_filename
959 : + "\", it can't be more than one character."));
960 : CATCH_END_SECTION()
961 :
962 14 : CATCH_START_SECTION("missing ')' in validator specification")
963 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
964 1 : tmpdir += "/shared/advgetopt";
965 2 : std::stringstream ss;
966 1 : ss << "mkdir -p " << tmpdir;
967 1 : if(system(ss.str().c_str()) != 0)
968 : {
969 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
970 0 : exit(1);
971 : }
972 2 : std::string const options_filename(tmpdir + "/bad-validator-parenthesis.ini");
973 :
974 1 : advgetopt::option const options[] =
975 : {
976 : advgetopt::define_option(
977 : advgetopt::Name("verbose")
978 : , advgetopt::ShortName('v')
979 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
980 : , advgetopt::Help("a verbose like option, select it or not.")
981 : ),
982 : advgetopt::end_options()
983 : };
984 :
985 1 : advgetopt::options_environment options_environment;
986 1 : options_environment.f_project_name = "bad-validator-parenthesis";
987 1 : options_environment.f_options = options;
988 1 : options_environment.f_options_files_directory = tmpdir.c_str();
989 1 : options_environment.f_environment_variable_name = nullptr;
990 1 : options_environment.f_help_header = "Usage: test invalid validator specification";
991 :
992 : {
993 2 : std::ofstream options_file;
994 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
995 1 : CATCH_REQUIRE(options_file.good());
996 1 : options_file <<
997 : "# Auto-generated\n"
998 :
999 : "[bad-validator]\n"
1000 : "shortname=b\n"
1001 : "default='Invalid Stuff'\n"
1002 : "help=Testing that a validator with parenthesis must have the ')'\n"
1003 : "validator=regex(\"missing ')'\"\n"
1004 : "allowed=command-line,environment-variable,configuration-file\n"
1005 : ;
1006 : }
1007 :
1008 1 : char const * sub_cargv[] =
1009 : {
1010 : "tests/unittests/invalid_validator_specification",
1011 : "--verbose",
1012 : nullptr
1013 : };
1014 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1015 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1016 :
1017 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1018 : , advgetopt::getopt_logic_error
1019 : , Catch::Matchers::ExceptionMessage(
1020 : "getopt_logic_error: invalid validator parameter definition: \"regex(\"missing ')'\"\", the ')' is missing."));
1021 : CATCH_END_SECTION()
1022 :
1023 14 : CATCH_START_SECTION("alias with help")
1024 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
1025 1 : tmpdir += "/shared/advgetopt";
1026 2 : std::stringstream ss;
1027 1 : ss << "mkdir -p " << tmpdir;
1028 1 : if(system(ss.str().c_str()) != 0)
1029 : {
1030 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1031 0 : exit(1);
1032 : }
1033 2 : std::string const options_filename(tmpdir + "/alias-with-help.ini");
1034 :
1035 1 : advgetopt::option const options[] =
1036 : {
1037 : advgetopt::define_option(
1038 : advgetopt::Name("verbose")
1039 : , advgetopt::ShortName('v')
1040 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1041 : , advgetopt::Help("a verbose like option, select it or not.")
1042 : ),
1043 : advgetopt::end_options()
1044 : };
1045 :
1046 1 : advgetopt::options_environment options_environment;
1047 1 : options_environment.f_project_name = "alias-with-help";
1048 1 : options_environment.f_options = options;
1049 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1050 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1051 1 : options_environment.f_environment_variable_name = nullptr;
1052 1 : options_environment.f_help_header = "Usage: test invalid validator specification";
1053 :
1054 : {
1055 2 : std::ofstream options_file;
1056 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1057 1 : CATCH_REQUIRE(options_file.good());
1058 1 : options_file <<
1059 : "# Auto-generated\n"
1060 :
1061 : "[licence]\n"
1062 : "shortname=l\n"
1063 : "default='Invalid Stuff'\n"
1064 : "alias=license\n"
1065 : "help=Testing that an alias can't accept a help string\n"
1066 : "allowed=command-line,environment-variable,configuration-file\n"
1067 : ;
1068 : }
1069 :
1070 1 : char const * sub_cargv[] =
1071 : {
1072 : "tests/unittests/invalid_alias_specification",
1073 : "--verbose",
1074 : nullptr
1075 : };
1076 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1077 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1078 :
1079 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1080 : , advgetopt::getopt_logic_error
1081 : , Catch::Matchers::ExceptionMessage(
1082 : "getopt_logic_error: option \"licence\" is an alias and as such it can't include a help=... parameter in \""
1083 : + options_filename
1084 : + "\"."));
1085 : CATCH_END_SECTION()
1086 :
1087 14 : CATCH_START_SECTION("no-name alias")
1088 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
1089 1 : tmpdir += "/shared/advgetopt";
1090 2 : std::stringstream ss;
1091 1 : ss << "mkdir -p " << tmpdir;
1092 1 : if(system(ss.str().c_str()) != 0)
1093 : {
1094 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1095 0 : exit(1);
1096 : }
1097 2 : std::string const options_filename(tmpdir + "/no-name-alias.ini");
1098 :
1099 1 : advgetopt::option const options[] =
1100 : {
1101 : advgetopt::define_option(
1102 : advgetopt::Name("verbose")
1103 : , advgetopt::ShortName('v')
1104 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1105 : , advgetopt::Help("a verbose like option, select it or not.")
1106 : ),
1107 : advgetopt::end_options()
1108 : };
1109 :
1110 1 : advgetopt::options_environment options_environment;
1111 1 : options_environment.f_project_name = "no-name-alias";
1112 1 : options_environment.f_options = options;
1113 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1114 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1115 1 : options_environment.f_environment_variable_name = nullptr;
1116 1 : options_environment.f_help_header = "Usage: test alias with no name specified";
1117 :
1118 : {
1119 2 : std::ofstream options_file;
1120 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1121 1 : CATCH_REQUIRE(options_file.good());
1122 1 : options_file <<
1123 : "# Auto-generated\n"
1124 :
1125 : "[foo]\n"
1126 : "shortname=f\n"
1127 : "default='Invalid Stuff'\n"
1128 : "alias=\n" // name missing (with an equal)
1129 : "allowed=command-line\n"
1130 : ;
1131 : }
1132 :
1133 1 : char const * sub_cargv[] =
1134 : {
1135 : "tests/unittests/non_existant_alias",
1136 : "--verbose",
1137 : nullptr
1138 : };
1139 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1140 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1141 :
1142 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1143 : , advgetopt::getopt_logic_error
1144 : , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
1145 : CATCH_END_SECTION()
1146 :
1147 14 : CATCH_START_SECTION("no-name alias v2")
1148 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
1149 1 : tmpdir += "/shared/advgetopt";
1150 2 : std::stringstream ss;
1151 1 : ss << "mkdir -p " << tmpdir;
1152 1 : if(system(ss.str().c_str()) != 0)
1153 : {
1154 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1155 0 : exit(1);
1156 : }
1157 2 : std::string const options_filename(tmpdir + "/no-name-alias-v2.ini");
1158 :
1159 1 : advgetopt::option const options[] =
1160 : {
1161 : advgetopt::define_option(
1162 : advgetopt::Name("verbose")
1163 : , advgetopt::ShortName('v')
1164 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1165 : , advgetopt::Help("a verbose like option, select it or not.")
1166 : ),
1167 : advgetopt::end_options()
1168 : };
1169 :
1170 1 : advgetopt::options_environment options_environment;
1171 1 : options_environment.f_project_name = "no-name-alias-v2";
1172 1 : options_environment.f_options = options;
1173 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1174 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1175 1 : options_environment.f_environment_variable_name = nullptr;
1176 1 : options_environment.f_help_header = "Usage: test alias with no name specified";
1177 :
1178 : {
1179 2 : std::ofstream options_file;
1180 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1181 1 : CATCH_REQUIRE(options_file.good());
1182 1 : options_file <<
1183 : "# Auto-generated\n"
1184 :
1185 : "[foo]\n"
1186 : "shortname=f\n"
1187 : "default='Invalid Stuff'\n"
1188 : "alias\n" // name missing (no equal)
1189 : "allowed=command-line\n"
1190 : ;
1191 : }
1192 :
1193 1 : char const * sub_cargv[] =
1194 : {
1195 : "tests/unittests/non_existant_alias",
1196 : "--verbose",
1197 : nullptr
1198 : };
1199 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1200 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1201 :
1202 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1203 : , advgetopt::getopt_logic_error
1204 : , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
1205 : CATCH_END_SECTION()
1206 :
1207 14 : CATCH_START_SECTION("non-existant alias")
1208 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir);
1209 1 : tmpdir += "/shared/advgetopt";
1210 2 : std::stringstream ss;
1211 1 : ss << "mkdir -p " << tmpdir;
1212 1 : if(system(ss.str().c_str()) != 0)
1213 : {
1214 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1215 0 : exit(1);
1216 : }
1217 2 : std::string const options_filename(tmpdir + "/non-existant-alias.ini");
1218 :
1219 1 : advgetopt::option const options[] =
1220 : {
1221 : advgetopt::define_option(
1222 : advgetopt::Name("verbose")
1223 : , advgetopt::ShortName('v')
1224 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1225 : , advgetopt::Help("a verbose like option, select it or not.")
1226 : ),
1227 : advgetopt::end_options()
1228 : };
1229 :
1230 1 : advgetopt::options_environment options_environment;
1231 1 : options_environment.f_project_name = "non-existant-alias";
1232 1 : options_environment.f_options = options;
1233 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1234 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1235 1 : options_environment.f_environment_variable_name = nullptr;
1236 1 : options_environment.f_help_header = "Usage: test invalid validator specification";
1237 :
1238 : {
1239 2 : std::ofstream options_file;
1240 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1241 1 : CATCH_REQUIRE(options_file.good());
1242 1 : options_file <<
1243 : "# Auto-generated\n"
1244 :
1245 : "[foo]\n"
1246 : "shortname=f\n"
1247 : "default='Invalid Stuff'\n"
1248 : "alias=bar\n" // option "bar" missing
1249 : "allowed=command-line\n"
1250 : ;
1251 : }
1252 :
1253 1 : char const * sub_cargv[] =
1254 : {
1255 : "tests/unittests/non_existant_alias",
1256 : "--verbose",
1257 : nullptr
1258 : };
1259 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1260 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1261 :
1262 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1263 : , advgetopt::getopt_logic_error
1264 : , Catch::Matchers::ExceptionMessage("getopt_logic_error: no option named \"bar\" to satisfy the alias of \"foo\"."));
1265 : CATCH_END_SECTION()
1266 13 : }
1267 :
1268 :
1269 :
1270 :
1271 :
1272 :
1273 :
1274 :
1275 :
1276 : // vim: ts=4 sw=4 et
|