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 1 : opt.define_environment_variable_data();
546 :
547 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"1001 meters\" given to parameter --size is not considered valid.");
548 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"valid.cpp\" given to parameter --files is not considered valid.");
549 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"auto-build\" given to parameter --from is not considered valid.");
550 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"black\" given to parameter --more is not considered valid.");
551 1 : opt.parse_environment_variable();
552 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
553 : }
554 : CATCH_END_SECTION()
555 :
556 12 : CATCH_START_SECTION("Check with validators in the definition")
557 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
558 1 : tmpdir += "/shared/advgetopt-validators-in-table";
559 2 : std::stringstream ss;
560 1 : ss << "mkdir -p " << tmpdir;
561 1 : if(system(ss.str().c_str()) != 0)
562 : {
563 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
564 0 : exit(1);
565 : }
566 2 : std::string const options_filename(tmpdir + "/unittest.ini");
567 :
568 1 : advgetopt::option const valid_options_from_file_list[] =
569 : {
570 : advgetopt::define_option(
571 : advgetopt::Name("verbose")
572 : , advgetopt::ShortName('v')
573 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
574 : , advgetopt::Help("a verbose like option, select it or not.")
575 : ),
576 : advgetopt::define_option(
577 : advgetopt::Name("size")
578 : , advgetopt::ShortName('s')
579 : , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED>())
580 : , advgetopt::Help("Specify the size.")
581 : , advgetopt::Validator("integer(0...100)")
582 : , advgetopt::DefaultValue("31")
583 : ),
584 : advgetopt::define_option(
585 : advgetopt::Name("files")
586 : , advgetopt::ShortName('f')
587 : , advgetopt::Help("List of file names")
588 : , advgetopt::Validator("/.*\\.txt/i")
589 : , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED, advgetopt::GETOPT_FLAG_MULTIPLE>())
590 : ),
591 : advgetopt::define_option(
592 : advgetopt::Name("from")
593 : , advgetopt::ShortName('F')
594 : , advgetopt::Help("Request for the geographcal location representing the origin of the files; optionally you can specify the format")
595 : , advgetopt::Validator("integer")
596 : , advgetopt::Flags(advgetopt::all_flags<>())
597 : ),
598 : advgetopt::define_option(
599 : advgetopt::Name("more")
600 : , advgetopt::ShortName('m')
601 : , advgetopt::Help("Allow for more stuff to be added")
602 : , advgetopt::Validator("regex(\"purple|yellow|blue|red|green|orange|brown\")")
603 : , advgetopt::Flags(advgetopt::all_flags<advgetopt::GETOPT_FLAG_REQUIRED, advgetopt::GETOPT_FLAG_SHOW_USAGE_ON_ERROR>())
604 : , advgetopt::DefaultValue("More Stuff")
605 : ),
606 : advgetopt::end_options()
607 : };
608 :
609 1 : advgetopt::options_environment valid_options_from_file;
610 1 : valid_options_from_file.f_project_name = "unittest";
611 1 : valid_options_from_file.f_options = valid_options_from_file_list;
612 1 : valid_options_from_file.f_options_files_directory = tmpdir.c_str();
613 1 : valid_options_from_file.f_environment_variable_name = "ADVGETOPT_TEST_OPTIONS";
614 1 : valid_options_from_file.f_help_header = "Usage: test valid options from file";
615 :
616 1 : snapdev::safe_setenv env("ADVGETOPT_TEST_OPTIONS"
617 : , "--verbose"
618 : " --more purple"
619 : " -f left.txt center.txt right.txt"
620 : " --size 19"
621 : " --from"
622 2 : " --output destination.txt");
623 :
624 : {
625 2 : std::ofstream options_file;
626 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
627 1 : CATCH_REQUIRE(options_file.good());
628 1 : options_file <<
629 : "# Auto-generated\n"
630 :
631 : "[output]\n"
632 : "shortname=o\n"
633 : "default=a.out\n"
634 : "help=output file\n"
635 : "allowed=environment-variable\n"
636 : "required\n"
637 :
638 : "[license]\n"
639 : "shortname=l\n"
640 : "help=show this test license\n"
641 : "allowed=command-line\n"
642 : "no-arguments\n"
643 :
644 : "[licence]\n"
645 : "alias=license\n"
646 : "allowed=command-line\n"
647 : "no-arguments\n"
648 : ;
649 : }
650 :
651 1 : char const * sub_cargv[] =
652 : {
653 : "tests/unittests/valid_options_files",
654 : "--verbose",
655 : "--licence",
656 : nullptr
657 : };
658 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
659 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
660 :
661 2 : advgetopt::getopt opt(valid_options_from_file, sub_argc, sub_argv);
662 :
663 : // check that the result is valid
664 :
665 : // an invalid parameter, MUST NOT EXIST
666 1 : CATCH_REQUIRE(opt.get_option("invalid-parameter") == nullptr);
667 1 : CATCH_REQUIRE_FALSE(opt.is_defined("invalid-parameter"));
668 :
669 : // the valid parameter
670 1 : CATCH_REQUIRE(opt.is_defined("verbose"));
671 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
672 1 : CATCH_REQUIRE(opt.size("verbose") == 1);
673 :
674 : // "--more"
675 1 : CATCH_REQUIRE(opt.is_defined("more"));
676 1 : CATCH_REQUIRE(opt.get_string("more") == "purple");
677 1 : CATCH_REQUIRE(opt.get_default("more") == "More Stuff");
678 1 : CATCH_REQUIRE(opt.size("more") == 1);
679 :
680 : // "--size <value>"
681 1 : CATCH_REQUIRE(opt.is_defined("size"));
682 1 : CATCH_REQUIRE(opt.get_string("size") == "19");
683 1 : CATCH_REQUIRE(opt.get_string("size", 0) == "19");
684 1 : CATCH_REQUIRE(opt.get_default("size") == "31");
685 1 : CATCH_REQUIRE(opt.size("size") == 1);
686 1 : CATCH_REQUIRE(opt.get_long("size") == 19);
687 :
688 : // "--files"
689 1 : CATCH_REQUIRE(opt.is_defined("files"));
690 1 : CATCH_REQUIRE(opt.get_string("files") == "left.txt");
691 1 : CATCH_REQUIRE(opt.get_string("files", 0) == "left.txt");
692 1 : CATCH_REQUIRE(opt.get_string("files", 1) == "center.txt");
693 1 : CATCH_REQUIRE(opt.get_string("files", 2) == "right.txt");
694 1 : CATCH_REQUIRE(opt.get_default("files").empty());
695 1 : CATCH_REQUIRE(opt.size("files") == 3);
696 :
697 : // "--from"
698 1 : CATCH_REQUIRE(opt.is_defined("from"));
699 1 : CATCH_REQUIRE(opt.size("from") == 1);
700 1 : CATCH_REQUIRE(opt.get_string("from") == "");
701 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
702 1 : CATCH_REQUIRE(opt.get_long("from") == -1);
703 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
704 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
705 1 : CATCH_REQUIRE(opt.get_long("from") == -1);
706 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
707 1 : CATCH_REQUIRE(opt.get_default("from").empty());
708 :
709 : // "--output"
710 1 : CATCH_REQUIRE(opt.is_defined("output"));
711 1 : CATCH_REQUIRE(opt.get_string("output") == "destination.txt"); // same as index = 0
712 1 : CATCH_REQUIRE(opt.get_string("output", 0) == "destination.txt");
713 1 : CATCH_REQUIRE(opt.get_default("output") == "a.out");
714 1 : CATCH_REQUIRE(opt.size("output") == 1);
715 :
716 : // "--from"
717 1 : CATCH_REQUIRE(opt.is_defined("license"));
718 1 : CATCH_REQUIRE(opt.get_string("license") == "");
719 1 : CATCH_REQUIRE(opt.get_default("license").empty());
720 1 : CATCH_REQUIRE(opt.size("license") == 1);
721 :
722 : // other parameters
723 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
724 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
725 :
726 1 : char const * sub_cargv2[] =
727 : {
728 : "this/is/ignored",
729 : "--from",
730 : "1001",
731 : nullptr
732 : };
733 1 : int const sub_argc2(sizeof(sub_cargv2) / sizeof(sub_cargv2[0]) - 1);
734 1 : char ** sub_argv2 = const_cast<char **>(sub_cargv2);
735 :
736 1 : opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
737 :
738 : // "--from"
739 1 : CATCH_REQUIRE(opt.is_defined("from"));
740 1 : CATCH_REQUIRE(opt.size("from") == 1);
741 1 : CATCH_REQUIRE(opt.get_string("from") == "1001");
742 1 : CATCH_REQUIRE(opt.get_long("from") == 1001);
743 1 : CATCH_REQUIRE(opt.get_default("from").empty());
744 :
745 : // other parameters
746 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
747 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
748 :
749 : // keep the last value...
750 : //
751 1 : opt.parse_environment_variable();
752 :
753 : // "--from"
754 1 : CATCH_REQUIRE(opt.is_defined("from"));
755 1 : CATCH_REQUIRE(opt.size("from") == 1);
756 1 : CATCH_REQUIRE(opt.get_string("from") == "");
757 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: invalid number () in parameter --from at offset 0.");
758 1 : CATCH_REQUIRE(opt.get_long("from") == -1);
759 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
760 1 : CATCH_REQUIRE(opt.get_default("from").empty());
761 :
762 : // other parameters
763 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
764 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
765 :
766 : // a reset will restore the state
767 : //
768 1 : opt.reset();
769 :
770 : // the valid parameter
771 1 : CATCH_REQUIRE_FALSE(opt.is_defined("verbose"));
772 1 : CATCH_REQUIRE(opt.get_default("verbose").empty());
773 1 : CATCH_REQUIRE(opt.size("verbose") == 0);
774 :
775 : // "--from"
776 1 : CATCH_REQUIRE_FALSE(opt.is_defined("from"));
777 1 : CATCH_REQUIRE(opt.get_default("from").empty());
778 1 : CATCH_REQUIRE(opt.size("from") == 0);
779 :
780 1 : opt.parse_environment_variable();
781 1 : opt.parse_arguments(sub_argc2, sub_argv2, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
782 :
783 : // "--from"
784 1 : CATCH_REQUIRE(opt.is_defined("from"));
785 1 : CATCH_REQUIRE(opt.get_string("from") == "1001");
786 1 : CATCH_REQUIRE(opt.get_long("from") == 1001);
787 1 : CATCH_REQUIRE(opt.get_default("from").empty());
788 1 : CATCH_REQUIRE(opt.size("from") == 1);
789 :
790 : // other parameters
791 1 : CATCH_REQUIRE(opt.get_program_name() == "valid_options_files");
792 1 : CATCH_REQUIRE(opt.get_program_fullname() == "tests/unittests/valid_options_files");
793 :
794 : // test that the validators do work here (i.e. generate errors as
795 : // expected when we use the wrong options.)
796 : //
797 1 : char const * sub_cargv3[] =
798 : {
799 : "this/is/ignored",
800 : "--size",
801 : "1001",
802 : "-f",
803 : "valid.cpp",
804 : "--from",
805 : "51",
806 : "--more",
807 : "black",
808 : nullptr
809 : };
810 1 : int const sub_argc3(sizeof(sub_cargv3) / sizeof(sub_cargv3[0]) - 1);
811 1 : char ** sub_argv3 = const_cast<char **>(sub_cargv3);
812 :
813 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"1001\" given to parameter --size is not considered valid.");
814 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"valid.cpp\" given to parameter --files is not considered valid.");
815 1 : SNAP_CATCH2_NAMESPACE::push_expected_log("error: input \"black\" given to parameter --more is not considered valid.");
816 1 : opt.parse_arguments(sub_argc3, sub_argv3, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
817 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
818 : CATCH_END_SECTION()
819 6 : }
820 :
821 :
822 9 : CATCH_TEST_CASE("invalid_options_files", "[options][invalid][files]")
823 : {
824 14 : CATCH_START_SECTION("2+ section names")
825 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
826 1 : tmpdir += "/shared/advgetopt";
827 2 : std::stringstream ss;
828 1 : ss << "mkdir -p " << tmpdir;
829 1 : if(system(ss.str().c_str()) != 0)
830 : {
831 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
832 0 : exit(1);
833 : }
834 2 : std::string const options_filename(tmpdir + "/bad-section.ini");
835 :
836 1 : advgetopt::option const options[] =
837 : {
838 : advgetopt::define_option(
839 : advgetopt::Name("verbose")
840 : , advgetopt::ShortName('v')
841 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
842 : , advgetopt::Help("a verbose like option, select it or not.")
843 : ),
844 : advgetopt::end_options()
845 : };
846 :
847 1 : advgetopt::options_environment options_environment;
848 1 : options_environment.f_project_name = "bad-section";
849 1 : options_environment.f_options = options;
850 1 : options_environment.f_options_files_directory = tmpdir.c_str();
851 1 : options_environment.f_environment_variable_name = nullptr;
852 1 : options_environment.f_help_header = "Usage: test invalid section name";
853 :
854 : {
855 2 : std::ofstream options_file;
856 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
857 1 : CATCH_REQUIRE(options_file.good());
858 1 : options_file <<
859 : "# Auto-generated\n"
860 :
861 : "[invalid::name]\n"
862 : "shortname=m\n"
863 : "default='Invalid Stuff'\n"
864 : "help=Testing that a section name can't include \"::\"\n"
865 : "allowed=command-line,environment-variable,configuration-file\n"
866 : ;
867 : }
868 :
869 1 : char const * sub_cargv[] =
870 : {
871 : "tests/unittests/invalid_name_in_options_ini",
872 : "--verbose",
873 : nullptr
874 : };
875 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
876 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
877 :
878 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
879 : "error: option name \"shortname\" cannot be added to"
880 : " section \"invalid::name\" because this"
881 : " configuration only accepts one section level.");
882 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
883 : "error: option name \"default\" cannot be added to"
884 : " section \"invalid::name\" because this"
885 : " configuration only accepts one section level.");
886 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
887 : "error: option name \"help\" cannot be added to"
888 : " section \"invalid::name\" because this"
889 : " configuration only accepts one section level.");
890 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
891 : "error: option name \"allowed\" cannot be added to"
892 : " section \"invalid::name\" because this"
893 : " configuration only accepts one section level.");
894 2 : advgetopt::getopt::pointer_t opt(std::make_shared<advgetopt::getopt>(options_environment));
895 : try
896 : {
897 1 : opt->finish_parsing(sub_argc, sub_argv);
898 0 : CATCH_REQUIRE(false); // the library is expected to throw here
899 : }
900 2 : catch(advgetopt::getopt_exit const & e)
901 : {
902 1 : CATCH_REQUIRE(e.code() == 1);
903 1 : CATCH_REQUIRE(e.what() == std::string("getopt_exception: errors were found on your command line, environment variable, or configuration file."));
904 : }
905 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
906 :
907 1 : CATCH_REQUIRE(opt->size("invalid::name::shortname") == 0);
908 1 : CATCH_REQUIRE(opt->size("shortname") == 0);
909 : CATCH_END_SECTION()
910 :
911 14 : CATCH_START_SECTION("short name too long")
912 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
913 1 : tmpdir += "/shared/advgetopt";
914 2 : std::stringstream ss;
915 1 : ss << "mkdir -p " << tmpdir;
916 1 : if(system(ss.str().c_str()) != 0)
917 : {
918 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
919 0 : exit(1);
920 : }
921 2 : std::string const options_filename(tmpdir + "/bad-shortname.ini");
922 :
923 1 : advgetopt::option const options[] =
924 : {
925 : advgetopt::define_option(
926 : advgetopt::Name("verbose")
927 : , advgetopt::ShortName('v')
928 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
929 : , advgetopt::Help("a verbose like option, select it or not.")
930 : ),
931 : advgetopt::end_options()
932 : };
933 :
934 1 : advgetopt::options_environment options_environment;
935 1 : options_environment.f_project_name = "bad-shortname";
936 1 : options_environment.f_options = options;
937 1 : options_environment.f_options_files_directory = tmpdir.c_str();
938 1 : options_environment.f_environment_variable_name = nullptr;
939 1 : options_environment.f_help_header = "Usage: test invalid shortname";
940 :
941 : {
942 2 : std::ofstream options_file;
943 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
944 1 : CATCH_REQUIRE(options_file.good());
945 1 : options_file <<
946 : "# Auto-generated\n"
947 :
948 : "[badname]\n"
949 : "shortname=to\n"
950 : "default='Invalid Stuff'\n"
951 : "help=Testing that a shotname can't be 2 characters or more\n"
952 : "allowed=command-line,environment-variable,configuration-file\n"
953 : ;
954 : }
955 :
956 1 : char const * sub_cargv[] =
957 : {
958 : "tests/unittests/invalid_name_in_options_ini",
959 : "--verbose",
960 : nullptr
961 : };
962 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
963 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
964 :
965 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
966 : , advgetopt::getopt_logic_error
967 : , Catch::Matchers::ExceptionMessage(
968 : "getopt_logic_error: option \"badname\" has an invalid short name in \""
969 : + options_filename
970 : + "\", it can't be more than one character."));
971 : CATCH_END_SECTION()
972 :
973 14 : CATCH_START_SECTION("missing ')' in validator specification")
974 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
975 1 : tmpdir += "/shared/advgetopt";
976 2 : std::stringstream ss;
977 1 : ss << "mkdir -p " << tmpdir;
978 1 : if(system(ss.str().c_str()) != 0)
979 : {
980 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
981 0 : exit(1);
982 : }
983 2 : std::string const options_filename(tmpdir + "/bad-validator-parenthesis.ini");
984 :
985 1 : advgetopt::option const options[] =
986 : {
987 : advgetopt::define_option(
988 : advgetopt::Name("verbose")
989 : , advgetopt::ShortName('v')
990 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
991 : , advgetopt::Help("a verbose like option, select it or not.")
992 : ),
993 : advgetopt::end_options()
994 : };
995 :
996 1 : advgetopt::options_environment options_environment;
997 1 : options_environment.f_project_name = "bad-validator-parenthesis";
998 1 : options_environment.f_options = options;
999 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1000 1 : options_environment.f_environment_variable_name = nullptr;
1001 1 : options_environment.f_help_header = "Usage: test invalid validator specification";
1002 :
1003 : {
1004 2 : std::ofstream options_file;
1005 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1006 1 : CATCH_REQUIRE(options_file.good());
1007 1 : options_file <<
1008 : "# Auto-generated\n"
1009 :
1010 : "[bad-validator]\n"
1011 : "shortname=b\n"
1012 : "default='Invalid Stuff'\n"
1013 : "help=Testing that a validator with parenthesis must have the ')'\n"
1014 : "validator=regex(\"missing ')'\"\n"
1015 : "allowed=command-line,environment-variable,configuration-file\n"
1016 : ;
1017 : }
1018 :
1019 1 : char const * sub_cargv[] =
1020 : {
1021 : "tests/unittests/invalid_validator_specification",
1022 : "--verbose",
1023 : nullptr
1024 : };
1025 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1026 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1027 :
1028 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1029 : , advgetopt::getopt_logic_error
1030 : , Catch::Matchers::ExceptionMessage(
1031 : "getopt_logic_error: invalid validator parameter definition: \"regex(\"missing ')'\"\", the ')' is missing."));
1032 : CATCH_END_SECTION()
1033 :
1034 14 : CATCH_START_SECTION("alias with help")
1035 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
1036 1 : tmpdir += "/shared/advgetopt";
1037 2 : std::stringstream ss;
1038 1 : ss << "mkdir -p " << tmpdir;
1039 1 : if(system(ss.str().c_str()) != 0)
1040 : {
1041 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1042 0 : exit(1);
1043 : }
1044 2 : std::string const options_filename(tmpdir + "/alias-with-help.ini");
1045 :
1046 1 : advgetopt::option const options[] =
1047 : {
1048 : advgetopt::define_option(
1049 : advgetopt::Name("verbose")
1050 : , advgetopt::ShortName('v')
1051 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1052 : , advgetopt::Help("a verbose like option, select it or not.")
1053 : ),
1054 : advgetopt::end_options()
1055 : };
1056 :
1057 1 : advgetopt::options_environment options_environment;
1058 1 : options_environment.f_project_name = "alias-with-help";
1059 1 : options_environment.f_options = options;
1060 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1061 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1062 1 : options_environment.f_environment_variable_name = nullptr;
1063 1 : options_environment.f_help_header = "Usage: test invalid validator specification";
1064 :
1065 : {
1066 2 : std::ofstream options_file;
1067 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1068 1 : CATCH_REQUIRE(options_file.good());
1069 1 : options_file <<
1070 : "# Auto-generated\n"
1071 :
1072 : "[licence]\n"
1073 : "shortname=l\n"
1074 : "default='Invalid Stuff'\n"
1075 : "alias=license\n"
1076 : "help=Testing that an alias can't accept a help string\n"
1077 : "allowed=command-line,environment-variable,configuration-file\n"
1078 : ;
1079 : }
1080 :
1081 1 : char const * sub_cargv[] =
1082 : {
1083 : "tests/unittests/invalid_alias_specification",
1084 : "--verbose",
1085 : nullptr
1086 : };
1087 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1088 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1089 :
1090 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1091 : , advgetopt::getopt_logic_error
1092 : , Catch::Matchers::ExceptionMessage(
1093 : "getopt_logic_error: option \"licence\" is an alias and as such it can't include a help=... parameter in \""
1094 : + options_filename
1095 : + "\"."));
1096 : CATCH_END_SECTION()
1097 :
1098 14 : CATCH_START_SECTION("no-name alias")
1099 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
1100 1 : tmpdir += "/shared/advgetopt";
1101 2 : std::stringstream ss;
1102 1 : ss << "mkdir -p " << tmpdir;
1103 1 : if(system(ss.str().c_str()) != 0)
1104 : {
1105 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1106 0 : exit(1);
1107 : }
1108 2 : std::string const options_filename(tmpdir + "/no-name-alias.ini");
1109 :
1110 1 : advgetopt::option const options[] =
1111 : {
1112 : advgetopt::define_option(
1113 : advgetopt::Name("verbose")
1114 : , advgetopt::ShortName('v')
1115 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1116 : , advgetopt::Help("a verbose like option, select it or not.")
1117 : ),
1118 : advgetopt::end_options()
1119 : };
1120 :
1121 1 : advgetopt::options_environment options_environment;
1122 1 : options_environment.f_project_name = "no-name-alias";
1123 1 : options_environment.f_options = options;
1124 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1125 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1126 1 : options_environment.f_environment_variable_name = nullptr;
1127 1 : options_environment.f_help_header = "Usage: test alias with no name specified";
1128 :
1129 : {
1130 2 : std::ofstream options_file;
1131 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1132 1 : CATCH_REQUIRE(options_file.good());
1133 1 : options_file <<
1134 : "# Auto-generated\n"
1135 :
1136 : "[foo]\n"
1137 : "shortname=f\n"
1138 : "default='Invalid Stuff'\n"
1139 : "alias=\n" // name missing (with an equal)
1140 : "allowed=command-line\n"
1141 : ;
1142 : }
1143 :
1144 1 : char const * sub_cargv[] =
1145 : {
1146 : "tests/unittests/non_existant_alias",
1147 : "--verbose",
1148 : nullptr
1149 : };
1150 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1151 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1152 :
1153 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1154 : , advgetopt::getopt_logic_error
1155 : , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
1156 : CATCH_END_SECTION()
1157 :
1158 14 : CATCH_START_SECTION("no-name alias v2")
1159 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
1160 1 : tmpdir += "/shared/advgetopt";
1161 2 : std::stringstream ss;
1162 1 : ss << "mkdir -p " << tmpdir;
1163 1 : if(system(ss.str().c_str()) != 0)
1164 : {
1165 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1166 0 : exit(1);
1167 : }
1168 2 : std::string const options_filename(tmpdir + "/no-name-alias-v2.ini");
1169 :
1170 1 : advgetopt::option const options[] =
1171 : {
1172 : advgetopt::define_option(
1173 : advgetopt::Name("verbose")
1174 : , advgetopt::ShortName('v')
1175 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1176 : , advgetopt::Help("a verbose like option, select it or not.")
1177 : ),
1178 : advgetopt::end_options()
1179 : };
1180 :
1181 1 : advgetopt::options_environment options_environment;
1182 1 : options_environment.f_project_name = "no-name-alias-v2";
1183 1 : options_environment.f_options = options;
1184 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1185 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1186 1 : options_environment.f_environment_variable_name = nullptr;
1187 1 : options_environment.f_help_header = "Usage: test alias with no name specified";
1188 :
1189 : {
1190 2 : std::ofstream options_file;
1191 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1192 1 : CATCH_REQUIRE(options_file.good());
1193 1 : options_file <<
1194 : "# Auto-generated\n"
1195 :
1196 : "[foo]\n"
1197 : "shortname=f\n"
1198 : "default='Invalid Stuff'\n"
1199 : "alias\n" // name missing (no equal)
1200 : "allowed=command-line\n"
1201 : ;
1202 : }
1203 :
1204 1 : char const * sub_cargv[] =
1205 : {
1206 : "tests/unittests/non_existant_alias",
1207 : "--verbose",
1208 : nullptr
1209 : };
1210 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1211 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1212 :
1213 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1214 : , advgetopt::getopt_logic_error
1215 : , Catch::Matchers::ExceptionMessage("getopt_logic_error: the default value of your alias cannot be an empty string for \"foo\"."));
1216 : CATCH_END_SECTION()
1217 :
1218 14 : CATCH_START_SECTION("non-existant alias")
1219 2 : std::string tmpdir(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
1220 1 : tmpdir += "/shared/advgetopt";
1221 2 : std::stringstream ss;
1222 1 : ss << "mkdir -p " << tmpdir;
1223 1 : if(system(ss.str().c_str()) != 0)
1224 : {
1225 0 : std::cerr << "fatal error: creating sub-temporary directory \"" << tmpdir << "\" failed.\n";
1226 0 : exit(1);
1227 : }
1228 2 : std::string const options_filename(tmpdir + "/non-existant-alias.ini");
1229 :
1230 1 : advgetopt::option const options[] =
1231 : {
1232 : advgetopt::define_option(
1233 : advgetopt::Name("verbose")
1234 : , advgetopt::ShortName('v')
1235 : , advgetopt::Flags(advgetopt::standalone_all_flags<>())
1236 : , advgetopt::Help("a verbose like option, select it or not.")
1237 : ),
1238 : advgetopt::end_options()
1239 : };
1240 :
1241 1 : advgetopt::options_environment options_environment;
1242 1 : options_environment.f_project_name = "non-existant-alias";
1243 1 : options_environment.f_options = options;
1244 1 : options_environment.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1245 1 : options_environment.f_options_files_directory = tmpdir.c_str();
1246 1 : options_environment.f_environment_variable_name = nullptr;
1247 1 : options_environment.f_help_header = "Usage: test invalid validator specification";
1248 :
1249 : {
1250 2 : std::ofstream options_file;
1251 1 : options_file.open(options_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1252 1 : CATCH_REQUIRE(options_file.good());
1253 1 : options_file <<
1254 : "# Auto-generated\n"
1255 :
1256 : "[foo]\n"
1257 : "shortname=f\n"
1258 : "default='Invalid Stuff'\n"
1259 : "alias=bar\n" // option "bar" missing
1260 : "allowed=command-line\n"
1261 : ;
1262 : }
1263 :
1264 1 : char const * sub_cargv[] =
1265 : {
1266 : "tests/unittests/non_existant_alias",
1267 : "--verbose",
1268 : nullptr
1269 : };
1270 1 : int const sub_argc(sizeof(sub_cargv) / sizeof(sub_cargv[0]) - 1);
1271 1 : char ** sub_argv = const_cast<char **>(sub_cargv);
1272 :
1273 1 : CATCH_REQUIRE_THROWS_MATCHES(std::make_shared<advgetopt::getopt>(options_environment, sub_argc, sub_argv)
1274 : , advgetopt::getopt_logic_error
1275 : , Catch::Matchers::ExceptionMessage("getopt_logic_error: no option named \"bar\" to satisfy the alias of \"foo\"."));
1276 : CATCH_END_SECTION()
1277 13 : }
1278 :
1279 :
1280 :
1281 :
1282 :
1283 :
1284 :
1285 :
1286 :
1287 : // vim: ts=4 sw=4 et
|