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