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 : // advgetopt
21 : //
22 : #include <advgetopt/conf_file.h>
23 :
24 : #include <advgetopt/exception.h>
25 :
26 :
27 : // self
28 : //
29 : #include "catch_main.h"
30 :
31 :
32 : // snapdev
33 : //
34 : #include <snapdev/safe_setenv.h>
35 : #include <snapdev/tokenize_string.h>
36 :
37 :
38 : // C++
39 : //
40 : #include <fstream>
41 :
42 :
43 : // C
44 : //
45 : #include <unistd.h>
46 :
47 :
48 : // last include
49 : //
50 : #include <snapdev/poison.h>
51 :
52 :
53 :
54 :
55 :
56 :
57 :
58 3 : CATCH_TEST_CASE("configuration_spaces", "[config][getopt][valid]")
59 : {
60 2 : CATCH_START_SECTION("Verify Configuration Spaces")
61 : {
62 1114113 : for(int c(0); c < 0x110000; ++c)
63 : {
64 1114112 : if(c == '\r'
65 1114111 : || c == '\n')
66 : {
67 2 : CATCH_REQUIRE_FALSE(advgetopt::iswspace(c));
68 : }
69 1114110 : else if(std::iswspace(c))
70 : {
71 4 : CATCH_REQUIRE(advgetopt::iswspace(c));
72 : }
73 : else
74 : {
75 1114106 : CATCH_REQUIRE_FALSE(advgetopt::iswspace(c));
76 : }
77 : }
78 : }
79 : CATCH_END_SECTION()
80 1 : }
81 :
82 :
83 4 : CATCH_TEST_CASE("configuration_setup", "[config][getopt][valid]")
84 : {
85 4 : CATCH_START_SECTION("Check All Setups")
86 : {
87 : // 5 * 6 * 8 * 8 * 16 = 30720
88 6 : for(int count(0); count < 5; ++count)
89 : {
90 5 : int const id(rand());
91 10 : std::string const name("setup-file-" + std::to_string(id));
92 :
93 5 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("setup", name);
94 :
95 : {
96 10 : std::ofstream config_file;
97 5 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
98 5 : CATCH_REQUIRE(config_file.good());
99 5 : config_file <<
100 : "# Auto-generated\n"
101 : "param=optional\n"
102 : ;
103 : }
104 :
105 35 : for(int lc(static_cast<int>(advgetopt::line_continuation_t::line_continuation_single_line));
106 35 : lc <= static_cast<int>(advgetopt::line_continuation_t::line_continuation_semicolon);
107 : ++lc)
108 : {
109 270 : for(advgetopt::assignment_operator_t ao(0);
110 270 : ao <= advgetopt::ASSIGNMENT_OPERATOR_MASK;
111 : ++ao)
112 : {
113 1920 : for(advgetopt::comment_t c(0);
114 1920 : c < advgetopt::COMMENT_MASK;
115 : ++c)
116 : {
117 26880 : for(advgetopt::section_operator_t so(0);
118 26880 : so < advgetopt::SECTION_OPERATOR_MASK;
119 : ++so)
120 : {
121 25200 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
122 : , static_cast<advgetopt::line_continuation_t>(lc)
123 : , ao
124 : , c
125 50400 : , so);
126 :
127 25200 : advgetopt::assignment_operator_t real_ao(ao == 0 ? advgetopt::ASSIGNMENT_OPERATOR_EQUAL : ao);
128 :
129 25200 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
130 :
131 25200 : CATCH_REQUIRE(setup.is_valid());
132 50400 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
133 25200 : CATCH_REQUIRE(setup.get_filename() == fn.get());
134 25200 : CATCH_REQUIRE(setup.get_line_continuation() == static_cast<advgetopt::line_continuation_t>(lc));
135 25200 : CATCH_REQUIRE(setup.get_assignment_operator() == real_ao);
136 25200 : CATCH_REQUIRE(setup.get_comment() == c);
137 25200 : CATCH_REQUIRE(setup.get_section_operator() == so);
138 :
139 50400 : std::string const url(setup.get_config_url());
140 : //std::cerr << "+++ " << lc << " / " << ao << " / " << c << " / " << so << " URL [" << url << "]\n";
141 25200 : CATCH_REQUIRE(url.substr(0, 8) == "file:///");
142 :
143 25200 : CATCH_REQUIRE(url.substr(7, strlen(fn.get())) == fn.get());
144 :
145 25200 : std::string::size_type const qm_pos(url.find('?'));
146 25200 : if(qm_pos == std::string::npos)
147 : {
148 : // must have the defaults in this case
149 : //
150 0 : CATCH_REQUIRE(static_cast<advgetopt::line_continuation_t>(lc) == advgetopt::line_continuation_t::line_continuation_unix);
151 0 : CATCH_REQUIRE(real_ao == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
152 0 : CATCH_REQUIRE(c == (advgetopt::COMMENT_INI | advgetopt::COMMENT_SHELL));
153 0 : CATCH_REQUIRE(so == advgetopt::SECTION_OPERATOR_INI_FILE);
154 : }
155 : else
156 : {
157 50400 : std::string const qs(url.substr(qm_pos + 1));
158 :
159 50400 : std::vector<std::string> strings;
160 25200 : snapdev::tokenize_string(strings, qs, "&");
161 :
162 25200 : bool def_lc(true);
163 25200 : bool def_ao(true);
164 25200 : bool def_c(true);
165 25200 : bool def_so(true);
166 :
167 112140 : for(auto s : strings)
168 : {
169 86940 : std::string::size_type const eq_pos(s.find('='));
170 86940 : CATCH_REQUIRE(eq_pos != std::string::npos);
171 :
172 173880 : std::string const var_name(s.substr(0, eq_pos));
173 173880 : std::string const var_value(s.substr(eq_pos + 1));
174 :
175 86940 : if(var_name == "line-continuation")
176 : {
177 21000 : def_lc = false;
178 21000 : switch(static_cast<advgetopt::line_continuation_t>(lc))
179 : {
180 4200 : case advgetopt::line_continuation_t::line_continuation_single_line:
181 4200 : CATCH_REQUIRE(var_value == "single-line");
182 4200 : break;
183 :
184 4200 : case advgetopt::line_continuation_t::line_continuation_rfc_822:
185 4200 : CATCH_REQUIRE(var_value == "rfc-822");
186 4200 : break;
187 :
188 4200 : case advgetopt::line_continuation_t::line_continuation_msdos:
189 4200 : CATCH_REQUIRE(var_value == "msdos");
190 4200 : break;
191 :
192 0 : case advgetopt::line_continuation_t::line_continuation_unix:
193 0 : CATCH_REQUIRE(var_value == "unix");
194 0 : break;
195 :
196 4200 : case advgetopt::line_continuation_t::line_continuation_fortran:
197 4200 : CATCH_REQUIRE(var_value == "fortran");
198 4200 : break;
199 :
200 4200 : case advgetopt::line_continuation_t::line_continuation_semicolon:
201 4200 : CATCH_REQUIRE(var_value == "semi-colon");
202 4200 : break;
203 :
204 0 : default:
205 0 : CATCH_REQUIRE(("unknown_var_value for \"line-continuation\":" + var_value) == std::string());
206 0 : break;
207 :
208 : }
209 : }
210 65940 : else if(var_name == "assignment-operator")
211 : {
212 18900 : def_ao = false;
213 37800 : std::vector<std::string> operators;
214 18900 : snapdev::tokenize_string(operators, var_value, ",");
215 :
216 18900 : if((real_ao & advgetopt::ASSIGNMENT_OPERATOR_EQUAL) != 0)
217 : {
218 9450 : auto it(std::find(operators.begin(), operators.end(), "equal"));
219 9450 : CATCH_REQUIRE(it != operators.end());
220 9450 : operators.erase(it);
221 : }
222 18900 : if((real_ao & advgetopt::ASSIGNMENT_OPERATOR_COLON) != 0)
223 : {
224 12600 : auto it(std::find(operators.begin(), operators.end(), "colon"));
225 12600 : CATCH_REQUIRE(it != operators.end());
226 12600 : operators.erase(it);
227 : }
228 18900 : if((real_ao & advgetopt::ASSIGNMENT_OPERATOR_SPACE) != 0)
229 : {
230 12600 : auto it(std::find(operators.begin(), operators.end(), "space"));
231 12600 : CATCH_REQUIRE(it != operators.end());
232 12600 : operators.erase(it);
233 : }
234 :
235 18900 : CATCH_REQUIRE(operators.empty());
236 : }
237 47040 : else if(var_name == "comment")
238 : {
239 25200 : def_c = false;
240 50400 : std::vector<std::string> comments;
241 25200 : snapdev::tokenize_string(comments, var_value, ",");
242 :
243 25200 : if((c & advgetopt::COMMENT_INI) != 0)
244 : {
245 10800 : auto it(std::find(comments.begin(), comments.end(), "ini"));
246 10800 : CATCH_REQUIRE(it != comments.end());
247 10800 : comments.erase(it);
248 : }
249 25200 : if((c & advgetopt::COMMENT_SHELL) != 0)
250 : {
251 10800 : auto it(std::find(comments.begin(), comments.end(), "shell"));
252 10800 : CATCH_REQUIRE(it != comments.end());
253 10800 : comments.erase(it);
254 : }
255 25200 : if((c & advgetopt::COMMENT_CPP) != 0)
256 : {
257 10800 : auto it(std::find(comments.begin(), comments.end(), "cpp"));
258 10800 : CATCH_REQUIRE(it != comments.end());
259 10800 : comments.erase(it);
260 : }
261 25200 : if(c == advgetopt::COMMENT_NONE)
262 : {
263 3600 : auto it(std::find(comments.begin(), comments.end(), "none"));
264 3600 : CATCH_REQUIRE(it != comments.end());
265 3600 : comments.erase(it);
266 : }
267 :
268 25200 : CATCH_REQUIRE(comments.empty());
269 : }
270 21840 : else if(var_name == "section-operator")
271 : {
272 21840 : def_so = false;
273 43680 : std::vector<std::string> section_operators;
274 21840 : snapdev::tokenize_string(section_operators, var_value, ",");
275 :
276 21840 : if((so & advgetopt::SECTION_OPERATOR_C) != 0)
277 : {
278 11760 : auto it(std::find(section_operators.begin(), section_operators.end(), "c"));
279 11760 : CATCH_REQUIRE(it != section_operators.end());
280 11760 : section_operators.erase(it);
281 : }
282 21840 : if((so & advgetopt::SECTION_OPERATOR_CPP) != 0)
283 : {
284 11760 : auto it(std::find(section_operators.begin(), section_operators.end(), "cpp"));
285 11760 : CATCH_REQUIRE(it != section_operators.end());
286 11760 : section_operators.erase(it);
287 : }
288 21840 : if((so & advgetopt::SECTION_OPERATOR_BLOCK) != 0)
289 : {
290 11760 : auto it(std::find(section_operators.begin(), section_operators.end(), "block"));
291 11760 : CATCH_REQUIRE(it != section_operators.end());
292 11760 : section_operators.erase(it);
293 : }
294 21840 : if((so & advgetopt::SECTION_OPERATOR_INI_FILE) != 0)
295 : {
296 10080 : auto it(std::find(section_operators.begin(), section_operators.end(), "ini-file"));
297 10080 : CATCH_REQUIRE(it != section_operators.end());
298 10080 : section_operators.erase(it);
299 : }
300 :
301 21840 : CATCH_REQUIRE(section_operators.empty());
302 : }
303 : else
304 : {
305 0 : CATCH_REQUIRE(("unknown var_name = " + var_name) == std::string());
306 : }
307 : }
308 :
309 25200 : if(def_lc)
310 : {
311 4200 : CATCH_REQUIRE(static_cast<advgetopt::line_continuation_t>(lc) == advgetopt::line_continuation_t::line_continuation_unix);
312 : }
313 25200 : if(def_ao)
314 : {
315 6300 : CATCH_REQUIRE(real_ao == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
316 : }
317 25200 : if(def_c)
318 : {
319 0 : CATCH_REQUIRE(c == (advgetopt::COMMENT_INI | advgetopt::COMMENT_SHELL));
320 : }
321 : }
322 : }
323 : }
324 : }
325 : }
326 : }
327 : }
328 : CATCH_END_SECTION()
329 :
330 4 : CATCH_START_SECTION("Check non-existant filename")
331 : {
332 1 : advgetopt::conf_file_setup setup(
333 : "/etc/advgetopt/unknown-file.conf"
334 : , advgetopt::line_continuation_t::line_continuation_fortran
335 : , advgetopt::ASSIGNMENT_OPERATOR_COLON
336 : , advgetopt::COMMENT_INI
337 2 : , advgetopt::SECTION_OPERATOR_CPP);
338 :
339 1 : CATCH_REQUIRE(setup.get_original_filename() == "/etc/advgetopt/unknown-file.conf");
340 :
341 1 : CATCH_REQUIRE(setup.is_valid());
342 1 : CATCH_REQUIRE(setup.get_filename() == "/etc/advgetopt/unknown-file.conf");
343 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_fortran);
344 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_COLON);
345 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_INI);
346 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_CPP);
347 :
348 1 : CATCH_REQUIRE(setup.get_config_url() == "file:///etc/advgetopt/unknown-file.conf?line-continuation=fortran&assignment-operator=colon&comment=ini§ion-operator=cpp");
349 : }
350 : CATCH_END_SECTION()
351 2 : }
352 :
353 :
354 :
355 3 : CATCH_TEST_CASE("config_reload_tests", "[config][getopt][valid]")
356 : {
357 2 : CATCH_START_SECTION("Load a file, update it, verify it does not get reloaded")
358 : {
359 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("reload", "load-twice");
360 :
361 : {
362 2 : std::ofstream config_file;
363 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
364 1 : CATCH_REQUIRE(config_file.good());
365 1 : config_file <<
366 : "# Auto-generated\n"
367 : "param=value\n"
368 : "changing=without reloading is useless\n"
369 : "test=1009\n"
370 : ;
371 : }
372 :
373 2 : advgetopt::conf_file::pointer_t file1;
374 : {
375 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
376 : , advgetopt::line_continuation_t::line_continuation_single_line
377 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
378 : , advgetopt::COMMENT_SHELL
379 2 : , advgetopt::SECTION_OPERATOR_NONE);
380 :
381 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
382 :
383 1 : CATCH_REQUIRE(setup.is_valid());
384 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
385 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
386 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
387 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
388 :
389 1 : file1 = advgetopt::conf_file::get_conf_file(setup);
390 :
391 1 : CATCH_REQUIRE(file1->get_setup().get_config_url() == setup.get_config_url());
392 1 : CATCH_REQUIRE(file1->get_errno() == 0);
393 1 : CATCH_REQUIRE(file1->get_sections().empty());
394 1 : CATCH_REQUIRE(file1->get_parameters().size() == 3);
395 :
396 1 : CATCH_REQUIRE(file1->has_parameter("param"));
397 1 : CATCH_REQUIRE(file1->has_parameter("changing"));
398 1 : CATCH_REQUIRE(file1->has_parameter("test"));
399 :
400 1 : CATCH_REQUIRE(file1->get_parameter("param") == "value");
401 1 : CATCH_REQUIRE(file1->get_parameter("changing") == "without reloading is useless");
402 1 : CATCH_REQUIRE(file1->get_parameter("test") == "1009");
403 : }
404 :
405 : // change all the values now
406 : {
407 2 : std::ofstream config_file;
408 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
409 1 : CATCH_REQUIRE(config_file.good());
410 1 : config_file <<
411 : "# Auto-generated\n"
412 : "param=new data\n"
413 : "new=this is not even acknowledge\n"
414 : "changing=special value\n"
415 : "test=9010\n"
416 : "level=three\n"
417 : ;
418 : }
419 :
420 : // "reloading" that very same file has the old data
421 : {
422 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
423 : , advgetopt::line_continuation_t::line_continuation_single_line
424 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
425 : , advgetopt::COMMENT_SHELL
426 2 : , advgetopt::SECTION_OPERATOR_NONE);
427 :
428 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
429 :
430 1 : CATCH_REQUIRE(setup.is_valid());
431 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
432 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
433 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
434 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
435 :
436 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
437 :
438 : // exact same pointer
439 : //
440 1 : CATCH_REQUIRE(file == file1);
441 :
442 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
443 1 : CATCH_REQUIRE(file->get_errno() == 0);
444 1 : CATCH_REQUIRE(file->get_sections().empty());
445 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
446 :
447 1 : CATCH_REQUIRE(file->has_parameter("param"));
448 1 : CATCH_REQUIRE(file->has_parameter("changing"));
449 1 : CATCH_REQUIRE(file->has_parameter("test"));
450 :
451 1 : CATCH_REQUIRE(file->get_parameter("param") == "value");
452 1 : CATCH_REQUIRE(file->get_parameter("changing") == "without reloading is useless");
453 1 : CATCH_REQUIRE(file->get_parameter("test") == "1009");
454 : }
455 : }
456 : CATCH_END_SECTION()
457 1 : }
458 :
459 :
460 :
461 3 : CATCH_TEST_CASE("config_duplicated_variables", "[config][getopt][valid]")
462 : {
463 2 : CATCH_START_SECTION("file with the same variable defined multiple times")
464 : {
465 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("duplicated-variable", "multiple");
466 :
467 : {
468 2 : std::ofstream config_file;
469 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
470 1 : CATCH_REQUIRE(config_file.good());
471 1 : config_file <<
472 : "# Auto-generated\n"
473 : "unique = perfect \n"
474 : "multiple = defintions\n"
475 : "another = just fine \t\n"
476 : "multiple = value\r\n"
477 : "good = variable \n"
478 : "multiple = set\n"
479 : "more = data\t \n"
480 : ;
481 : }
482 :
483 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
484 : , advgetopt::line_continuation_t::line_continuation_single_line
485 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
486 : , advgetopt::COMMENT_SHELL
487 2 : , advgetopt::SECTION_OPERATOR_NONE);
488 :
489 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
490 :
491 1 : CATCH_REQUIRE(setup.is_valid());
492 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
493 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
494 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
495 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
496 :
497 2 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
498 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
499 : "warning: parameter \"multiple\" on line 5 in"
500 : " configuration file \""
501 2 : + std::string(fn.get())
502 3 : + "\" was found twice in the same configuration file.");
503 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
504 : "warning: parameter \"multiple\" on line 7 in"
505 : " configuration file \""
506 2 : + std::string(fn.get())
507 3 : + "\" was found twice in the same configuration file.");
508 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
509 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
510 :
511 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
512 1 : CATCH_REQUIRE(file->get_errno() == 0);
513 1 : CATCH_REQUIRE(file->get_sections().empty());
514 1 : CATCH_REQUIRE(file->get_parameters().size() == 5);
515 :
516 1 : CATCH_REQUIRE(file->has_parameter("unique"));
517 1 : CATCH_REQUIRE(file->has_parameter("another"));
518 1 : CATCH_REQUIRE(file->has_parameter("good"));
519 1 : CATCH_REQUIRE(file->has_parameter("more"));
520 1 : CATCH_REQUIRE(file->has_parameter("multiple"));
521 :
522 1 : CATCH_REQUIRE(file->get_parameter("unique") == "perfect");
523 1 : CATCH_REQUIRE(file->get_parameter("another") == "just fine");
524 1 : CATCH_REQUIRE(file->get_parameter("good") == "variable");
525 1 : CATCH_REQUIRE(file->get_parameter("more") == "data");
526 1 : CATCH_REQUIRE(file->get_parameter("multiple") == "set");
527 :
528 : // we get a warning while reading; but not when directly
529 : // accessing the file object
530 : //
531 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "multiple", "new value"));
532 1 : CATCH_REQUIRE(file->get_parameter("multiple") == "new value");
533 : }
534 : CATCH_END_SECTION()
535 1 : }
536 :
537 :
538 :
539 3 : CATCH_TEST_CASE("config_callback_calls", "[config][getopt][valid]")
540 : {
541 2 : CATCH_START_SECTION("setup a callback and test the set_parameter()/erase() functions")
542 : {
543 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("callback-variable", "callback");
544 :
545 : {
546 2 : std::ofstream config_file;
547 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
548 1 : CATCH_REQUIRE(config_file.good());
549 1 : config_file <<
550 : "# Auto-generated\n"
551 : "unique = perfect \n"
552 : "definition = long value here\n"
553 : "another = just fine \t\n"
554 : "multiple = value\r\n"
555 : "good = variable \n"
556 : "organized = set\n"
557 : "more = data\t \n"
558 : ;
559 : }
560 :
561 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
562 : , advgetopt::line_continuation_t::line_continuation_single_line
563 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
564 : , advgetopt::COMMENT_SHELL
565 2 : , advgetopt::SECTION_OPERATOR_NONE);
566 :
567 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
568 :
569 1 : CATCH_REQUIRE(setup.is_valid());
570 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
571 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
572 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
573 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
574 :
575 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
576 :
577 2 : struct conf_data
578 : {
579 : advgetopt::conf_file::pointer_t f_conf_file = advgetopt::conf_file::pointer_t();
580 : advgetopt::callback_action_t f_expected_action = advgetopt::callback_action_t::created;
581 : std::string f_expected_variable = std::string();
582 : std::string f_expected_value = std::string();
583 : };
584 2 : conf_data cf_data;
585 1 : cf_data.f_conf_file = file;
586 :
587 : struct conf_callback
588 : {
589 6 : void operator () (advgetopt::conf_file::pointer_t conf_file
590 : , advgetopt::callback_action_t action
591 : , std::string const & variable_name
592 : , std::string const & value)
593 : {
594 6 : CATCH_REQUIRE(conf_file == f_data->f_conf_file);
595 6 : CATCH_REQUIRE(action == f_data->f_expected_action);
596 6 : CATCH_REQUIRE(variable_name == f_data->f_expected_variable);
597 6 : CATCH_REQUIRE(value == f_data->f_expected_value);
598 6 : CATCH_REQUIRE(conf_file->get_parameter(variable_name) == f_data->f_expected_value);
599 6 : }
600 :
601 : conf_data * f_data = nullptr;
602 : };
603 1 : conf_callback cf;
604 1 : cf.f_data = &cf_data;
605 :
606 1 : advgetopt::conf_file::callback_id_t callback_id(file->add_callback(cf));
607 :
608 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
609 1 : CATCH_REQUIRE(file->get_errno() == 0);
610 1 : CATCH_REQUIRE_FALSE(file->was_modified());
611 1 : CATCH_REQUIRE(file->get_sections().empty());
612 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
613 :
614 1 : CATCH_REQUIRE(file->has_parameter("unique"));
615 1 : CATCH_REQUIRE(file->has_parameter("definition"));
616 1 : CATCH_REQUIRE(file->has_parameter("another"));
617 1 : CATCH_REQUIRE(file->has_parameter("multiple"));
618 1 : CATCH_REQUIRE(file->has_parameter("good"));
619 1 : CATCH_REQUIRE(file->has_parameter("organized"));
620 1 : CATCH_REQUIRE(file->has_parameter("more"));
621 :
622 1 : CATCH_REQUIRE(file->get_parameter("unique") == "perfect");
623 1 : CATCH_REQUIRE(file->get_parameter("definition") == "long value here");
624 1 : CATCH_REQUIRE(file->get_parameter("another") == "just fine");
625 1 : CATCH_REQUIRE(file->get_parameter("multiple") == "value");
626 1 : CATCH_REQUIRE(file->get_parameter("good") == "variable");
627 1 : CATCH_REQUIRE(file->get_parameter("organized") == "set");
628 1 : CATCH_REQUIRE(file->get_parameter("more") == "data");
629 :
630 : // updated action
631 : //
632 1 : cf_data.f_expected_action = advgetopt::callback_action_t::updated;
633 1 : cf_data.f_expected_variable = "multiple";
634 1 : cf_data.f_expected_value = "new value";
635 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "multiple", "new value"));
636 1 : CATCH_REQUIRE(file->was_modified());
637 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
638 1 : CATCH_REQUIRE(file->get_parameter("multiple") == "new value");
639 :
640 : // created action
641 : //
642 1 : cf_data.f_expected_action = advgetopt::callback_action_t::created;
643 1 : cf_data.f_expected_variable = "new-param";
644 1 : cf_data.f_expected_value = "with this value";
645 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "new_param", "with this value"));
646 1 : CATCH_REQUIRE(file->was_modified());
647 1 : CATCH_REQUIRE(file->get_parameters().size() == 8);
648 1 : CATCH_REQUIRE(file->has_parameter("new-param"));
649 1 : CATCH_REQUIRE(file->get_parameter("new-param") == "with this value");
650 1 : CATCH_REQUIRE(file->has_parameter("new_param"));
651 1 : CATCH_REQUIRE(file->get_parameter("new_param") == "with this value");
652 :
653 : // updated action when modifying
654 : //
655 1 : cf_data.f_expected_action = advgetopt::callback_action_t::updated;
656 1 : cf_data.f_expected_variable = "new-param";
657 1 : cf_data.f_expected_value = "change completely";
658 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "new_param", "change completely"));
659 1 : CATCH_REQUIRE(file->was_modified());
660 1 : CATCH_REQUIRE(file->get_parameters().size() == 8);
661 1 : CATCH_REQUIRE(file->has_parameter("new-param"));
662 1 : CATCH_REQUIRE(file->get_parameter("new-param") == "change completely");
663 1 : CATCH_REQUIRE(file->has_parameter("new_param"));
664 1 : CATCH_REQUIRE(file->get_parameter("new_param") == "change completely");
665 :
666 : // erased action
667 : //
668 1 : cf_data.f_expected_action = advgetopt::callback_action_t::erased;
669 1 : cf_data.f_expected_variable = "new-param";
670 1 : cf_data.f_expected_value = std::string();
671 1 : CATCH_REQUIRE(file->erase_parameter("new_param"));
672 1 : CATCH_REQUIRE(file->was_modified());
673 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
674 1 : CATCH_REQUIRE_FALSE(file->has_parameter("new-param"));
675 1 : CATCH_REQUIRE(file->get_parameter("new-param") == std::string());
676 1 : CATCH_REQUIRE_FALSE(file->has_parameter("new_param"));
677 1 : CATCH_REQUIRE(file->get_parameter("new_param") == std::string());
678 1 : CATCH_REQUIRE_FALSE(file->erase_parameter("new_param"));
679 :
680 : // created action again (because it was erased)
681 : //
682 1 : cf_data.f_expected_action = advgetopt::callback_action_t::created;
683 1 : cf_data.f_expected_variable = "new-param";
684 1 : cf_data.f_expected_value = "with this value";
685 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "new_param", "with this value"));
686 1 : CATCH_REQUIRE(file->was_modified());
687 1 : CATCH_REQUIRE(file->get_parameters().size() == 8);
688 1 : CATCH_REQUIRE(file->has_parameter("new-param"));
689 1 : CATCH_REQUIRE(file->get_parameter("new-param") == "with this value");
690 1 : CATCH_REQUIRE(file->has_parameter("new_param"));
691 1 : CATCH_REQUIRE(file->get_parameter("new_param") == "with this value");
692 :
693 1 : file->remove_callback(callback_id);
694 1 : cf_data.f_expected_action = advgetopt::callback_action_t::created;
695 1 : cf_data.f_expected_variable = "ignored";
696 1 : cf_data.f_expected_value = "ignored";
697 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "new_param", "unnoticed change"));
698 1 : CATCH_REQUIRE(file->was_modified());
699 1 : CATCH_REQUIRE(file->get_parameters().size() == 8);
700 1 : CATCH_REQUIRE(file->has_parameter("new-param"));
701 1 : CATCH_REQUIRE(file->get_parameter("new-param") == "unnoticed change");
702 1 : CATCH_REQUIRE(file->has_parameter("new_param"));
703 1 : CATCH_REQUIRE(file->get_parameter("new_param") == "unnoticed change");
704 :
705 : // further calls do nothing more
706 : //
707 1 : file->remove_callback(callback_id);
708 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "new_param", "still unnoticed"));
709 1 : CATCH_REQUIRE(file->was_modified());
710 1 : CATCH_REQUIRE(file->get_parameters().size() == 8);
711 1 : CATCH_REQUIRE(file->has_parameter("new-param"));
712 1 : CATCH_REQUIRE(file->get_parameter("new-param") == "still unnoticed");
713 1 : CATCH_REQUIRE(file->has_parameter("new_param"));
714 1 : CATCH_REQUIRE(file->get_parameter("new_param") == "still unnoticed");
715 :
716 : // and we can always re-add it
717 : //
718 1 : CATCH_REQUIRE(callback_id != file->add_callback(cf));
719 1 : cf_data.f_expected_action = advgetopt::callback_action_t::updated;
720 1 : cf_data.f_expected_variable = "new-param";
721 1 : cf_data.f_expected_value = "we're back";
722 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "new_param", "we're back"));
723 1 : CATCH_REQUIRE(file->was_modified());
724 1 : CATCH_REQUIRE(file->get_parameters().size() == 8);
725 1 : CATCH_REQUIRE(file->has_parameter("new-param"));
726 1 : CATCH_REQUIRE(file->get_parameter("new-param") == "we're back");
727 1 : CATCH_REQUIRE(file->has_parameter("new_param"));
728 1 : CATCH_REQUIRE(file->get_parameter("new_param") == "we're back");
729 :
730 : // until you save it remains true even if you were to restore the
731 : // state to "normal" (we do not keep a copy of the original value
732 : // as found in the file.)
733 : //
734 1 : CATCH_REQUIRE(file->was_modified());
735 : }
736 : CATCH_END_SECTION()
737 1 : }
738 :
739 :
740 :
741 8 : CATCH_TEST_CASE("config_line_continuation_tests", "[config][getopt][valid]")
742 : {
743 12 : CATCH_START_SECTION("single_line")
744 : {
745 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "single-line");
746 :
747 : {
748 2 : std::ofstream config_file;
749 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
750 1 : CATCH_REQUIRE(config_file.good());
751 1 : config_file <<
752 : "# Auto-generated\n"
753 : "normal=param\n"
754 : "\n"
755 : "rfc-822=start here\n"
756 : " continue=there\n"
757 : "\n"
758 : "msdos=end with &\n"
759 : " and-continue=on next line\n"
760 : "\n"
761 : "unix=end with \\\n"
762 : "to-continue=like this\n"
763 : "\n"
764 : "fortran=fortran is funny\n"
765 : "&since=it starts with an & on the following line\n"
766 : "\n"
767 : "semicolon=this ends with\n"
768 : "a=semi-colon only;\n"
769 : ;
770 : }
771 :
772 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
773 : , advgetopt::line_continuation_t::line_continuation_single_line
774 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
775 : , advgetopt::COMMENT_SHELL
776 2 : , advgetopt::SECTION_OPERATOR_NONE);
777 :
778 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
779 :
780 1 : CATCH_REQUIRE(setup.is_valid());
781 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
782 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
783 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
784 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
785 :
786 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
787 :
788 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
789 1 : CATCH_REQUIRE(file->get_errno() == 0);
790 1 : CATCH_REQUIRE(file->get_sections().empty());
791 1 : CATCH_REQUIRE(file->get_parameters().size() == 11);
792 :
793 1 : CATCH_REQUIRE(file->has_parameter("normal"));
794 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
795 1 : CATCH_REQUIRE(file->has_parameter("continue"));
796 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
797 1 : CATCH_REQUIRE(file->has_parameter("and-continue"));
798 1 : CATCH_REQUIRE(file->has_parameter("unix"));
799 1 : CATCH_REQUIRE(file->has_parameter("to-continue"));
800 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
801 1 : CATCH_REQUIRE(file->has_parameter("&since"));
802 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
803 1 : CATCH_REQUIRE(file->has_parameter("a"));
804 :
805 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
806 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start here");
807 1 : CATCH_REQUIRE(file->get_parameter("continue") == "there");
808 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with &");
809 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == "on next line");
810 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with \\");
811 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == "like this");
812 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funny");
813 1 : CATCH_REQUIRE(file->get_parameter("&since") == "it starts with an & on the following line");
814 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
815 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
816 :
817 1114113 : for(int c(0); c < 0x110000; ++c)
818 : {
819 1114112 : if(c == '=')
820 : {
821 1 : CATCH_REQUIRE(file->is_assignment_operator(c));
822 : }
823 : else
824 : {
825 1114111 : CATCH_REQUIRE_FALSE(file->is_assignment_operator(c));
826 : }
827 : }
828 : }
829 : CATCH_END_SECTION()
830 :
831 12 : CATCH_START_SECTION("rfc822")
832 : {
833 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "rfc822");
834 :
835 : {
836 2 : std::ofstream config_file;
837 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
838 1 : CATCH_REQUIRE(config_file.good());
839 1 : config_file <<
840 : "# Auto-generated\n"
841 : "normal=param\n"
842 : "\n"
843 : "rfc-822=start here\n"
844 : " continue=there\n"
845 : "\n"
846 : "msdos=end with &\n"
847 : " and-continue=on next line\n"
848 : "\n"
849 : "unix=end with \\\n"
850 : "to-continue=like this\n"
851 : "\n"
852 : "fortran=fortran is funny\n"
853 : "&since=it starts with an & on the following line\n"
854 : "\n"
855 : "semicolon=this ends with\n"
856 : "a=semi-colon only;\n"
857 : ;
858 : }
859 :
860 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
861 : , advgetopt::line_continuation_t::line_continuation_rfc_822
862 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
863 : , advgetopt::COMMENT_SHELL
864 2 : , advgetopt::SECTION_OPERATOR_NONE);
865 :
866 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
867 :
868 1 : CATCH_REQUIRE(setup.is_valid());
869 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_rfc_822);
870 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
871 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
872 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
873 :
874 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
875 :
876 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
877 1 : CATCH_REQUIRE(file->get_errno() == 0);
878 1 : CATCH_REQUIRE(file->get_sections().empty());
879 1 : CATCH_REQUIRE(file->get_parameters().size() == 9);
880 :
881 1 : CATCH_REQUIRE(file->has_parameter("normal"));
882 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
883 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
884 1 : CATCH_REQUIRE_FALSE(file->has_parameter("and-continue"));
885 1 : CATCH_REQUIRE(file->has_parameter("unix"));
886 1 : CATCH_REQUIRE(file->has_parameter("to-continue"));
887 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
888 1 : CATCH_REQUIRE(file->has_parameter("&since"));
889 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
890 1 : CATCH_REQUIRE(file->has_parameter("a"));
891 :
892 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
893 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start herecontinue=there");
894 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with &and-continue=on next line");
895 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == std::string());
896 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with \\");
897 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == "like this");
898 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funny");
899 1 : CATCH_REQUIRE(file->get_parameter("&since") == "it starts with an & on the following line");
900 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
901 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
902 : }
903 : CATCH_END_SECTION()
904 :
905 12 : CATCH_START_SECTION("msdos")
906 : {
907 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "msdos");
908 :
909 : {
910 2 : std::ofstream config_file;
911 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
912 1 : CATCH_REQUIRE(config_file.good());
913 1 : config_file <<
914 : "# Auto-generated\n"
915 : "normal=param\n"
916 : "\n"
917 : "rfc-822=start here\n"
918 : " continue=there\n"
919 : "\n"
920 : "msdos=end with &\n"
921 : " and-continue=on next line\n"
922 : "\n"
923 : "unix=end with \\\n"
924 : "to-continue=like this\n"
925 : "\n"
926 : "fortran=fortran is funny\n"
927 : "&since=it starts with an & on the following line\n"
928 : "\n"
929 : "semicolon=this ends with\n"
930 : "a=semi-colon only;\n"
931 : ;
932 : }
933 :
934 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
935 : , advgetopt::line_continuation_t::line_continuation_msdos
936 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
937 : , advgetopt::COMMENT_SHELL
938 2 : , advgetopt::SECTION_OPERATOR_NONE);
939 :
940 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
941 :
942 1 : CATCH_REQUIRE(setup.is_valid());
943 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_msdos);
944 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
945 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
946 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
947 :
948 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
949 :
950 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
951 1 : CATCH_REQUIRE(file->get_errno() == 0);
952 1 : CATCH_REQUIRE(file->get_sections().empty());
953 1 : CATCH_REQUIRE(file->get_parameters().size() == 10);
954 :
955 1 : CATCH_REQUIRE(file->has_parameter("normal"));
956 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
957 1 : CATCH_REQUIRE(file->has_parameter("continue"));
958 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
959 1 : CATCH_REQUIRE_FALSE(file->has_parameter("and-continue"));
960 1 : CATCH_REQUIRE(file->has_parameter("unix"));
961 1 : CATCH_REQUIRE(file->has_parameter("to-continue"));
962 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
963 1 : CATCH_REQUIRE(file->has_parameter("&since"));
964 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
965 1 : CATCH_REQUIRE(file->has_parameter("a"));
966 :
967 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
968 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start here");
969 1 : CATCH_REQUIRE(file->get_parameter("continue") == "there");
970 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with and-continue=on next line");
971 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == std::string());
972 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with \\");
973 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == "like this");
974 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funny");
975 1 : CATCH_REQUIRE(file->get_parameter("&since") == "it starts with an & on the following line");
976 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
977 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
978 : }
979 : CATCH_END_SECTION()
980 :
981 12 : CATCH_START_SECTION("unix")
982 : {
983 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "unix");
984 :
985 : {
986 2 : std::ofstream config_file;
987 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
988 1 : CATCH_REQUIRE(config_file.good());
989 1 : config_file <<
990 : "# Auto-generated\n"
991 : "normal=param\n"
992 : "\n"
993 : "rfc-822=start here\n"
994 : " continue=there\n"
995 : "\n"
996 : "msdos=end with &\n"
997 : " and-continue=on next line\n"
998 : "\n"
999 : "unix=end with \\\n"
1000 : "to-continue=like this\n"
1001 : "\n"
1002 : "fortran=fortran is funny\n"
1003 : "&since=it starts with an & on the following line\n"
1004 : "\n"
1005 : "semicolon=this ends with\n"
1006 : "a=semi-colon only;\n"
1007 : ;
1008 : }
1009 :
1010 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1011 : , advgetopt::line_continuation_t::line_continuation_unix
1012 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1013 : , advgetopt::COMMENT_SHELL
1014 2 : , advgetopt::SECTION_OPERATOR_NONE);
1015 :
1016 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1017 :
1018 1 : CATCH_REQUIRE(setup.is_valid());
1019 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1020 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1021 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1022 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1023 :
1024 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1025 :
1026 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1027 1 : CATCH_REQUIRE(file->get_errno() == 0);
1028 1 : CATCH_REQUIRE(file->get_sections().empty());
1029 1 : CATCH_REQUIRE(file->get_parameters().size() == 10);
1030 :
1031 1 : CATCH_REQUIRE(file->has_parameter("normal"));
1032 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
1033 1 : CATCH_REQUIRE(file->has_parameter("continue"));
1034 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
1035 1 : CATCH_REQUIRE(file->has_parameter("and-continue"));
1036 1 : CATCH_REQUIRE(file->has_parameter("unix"));
1037 1 : CATCH_REQUIRE_FALSE(file->has_parameter("to-continue"));
1038 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
1039 1 : CATCH_REQUIRE(file->has_parameter("&since"));
1040 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
1041 1 : CATCH_REQUIRE(file->has_parameter("a"));
1042 :
1043 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
1044 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start here");
1045 1 : CATCH_REQUIRE(file->get_parameter("continue") == "there");
1046 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with &");
1047 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == "on next line");
1048 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with to-continue=like this");
1049 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == std::string());
1050 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funny");
1051 1 : CATCH_REQUIRE(file->get_parameter("&since") == "it starts with an & on the following line");
1052 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
1053 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
1054 : }
1055 : CATCH_END_SECTION()
1056 :
1057 12 : CATCH_START_SECTION("fortran")
1058 : {
1059 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "fortran");
1060 :
1061 : {
1062 2 : std::ofstream config_file;
1063 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1064 1 : CATCH_REQUIRE(config_file.good());
1065 1 : config_file <<
1066 : "# Auto-generated\n"
1067 : "normal=param\n"
1068 : "\n"
1069 : "rfc-822=start here\n"
1070 : " continue=there\n"
1071 : "\n"
1072 : "msdos=end with &\n"
1073 : " and-continue=on next line\n"
1074 : "\n"
1075 : "unix=end with \\\n"
1076 : "to-continue=like this\n"
1077 : "\n"
1078 : "fortran=fortran is funny\n"
1079 : "&since=it starts with an & on the following line\n"
1080 : "\n"
1081 : "semicolon=this ends with\n"
1082 : "a=semi-colon only;\n"
1083 : ;
1084 : }
1085 :
1086 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1087 : , advgetopt::line_continuation_t::line_continuation_fortran
1088 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1089 : , advgetopt::COMMENT_SHELL
1090 2 : , advgetopt::SECTION_OPERATOR_NONE);
1091 :
1092 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1093 :
1094 1 : CATCH_REQUIRE(setup.is_valid());
1095 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_fortran);
1096 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1097 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1098 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1099 :
1100 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1101 :
1102 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1103 1 : CATCH_REQUIRE(file->get_errno() == 0);
1104 1 : CATCH_REQUIRE(file->get_sections().empty());
1105 1 : CATCH_REQUIRE(file->get_parameters().size() == 10);
1106 :
1107 1 : CATCH_REQUIRE(file->has_parameter("normal"));
1108 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
1109 1 : CATCH_REQUIRE(file->has_parameter("continue"));
1110 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
1111 1 : CATCH_REQUIRE(file->has_parameter("and-continue"));
1112 1 : CATCH_REQUIRE(file->has_parameter("unix"));
1113 1 : CATCH_REQUIRE(file->has_parameter("to-continue"));
1114 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
1115 1 : CATCH_REQUIRE_FALSE(file->has_parameter("&since"));
1116 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
1117 1 : CATCH_REQUIRE(file->has_parameter("a"));
1118 :
1119 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
1120 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start here");
1121 1 : CATCH_REQUIRE(file->get_parameter("continue") == "there");
1122 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with &");
1123 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == "on next line");
1124 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with \\");
1125 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == "like this");
1126 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funnysince=it starts with an & on the following line");
1127 1 : CATCH_REQUIRE(file->get_parameter("&since") == std::string());
1128 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
1129 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
1130 : }
1131 : CATCH_END_SECTION()
1132 :
1133 12 : CATCH_START_SECTION("semicolon")
1134 : {
1135 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "semicolon");
1136 :
1137 : {
1138 2 : std::ofstream config_file;
1139 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1140 1 : CATCH_REQUIRE(config_file.good());
1141 1 : config_file <<
1142 : "# Auto-generated\r\n"
1143 : "normal=param\r\n"
1144 : "\r\n"
1145 : "rfc-822=start here\r\n"
1146 : " continue=there\r\n"
1147 : "\r\n"
1148 : "msdos=end with &\r"
1149 : " and-continue=on next line\r\n"
1150 : "\r\n"
1151 : "unix=end with \\\r\n"
1152 : "to-continue=like this\r"
1153 : "\r\n"
1154 : "fortran=fortran is funny\r\n"
1155 : "&since=it starts with an & on the following line\r\n"
1156 : "\r"
1157 : "semicolon=this ends with\r\n"
1158 : "a=semi-colon only;\r\n"
1159 : ;
1160 : }
1161 :
1162 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1163 : , advgetopt::line_continuation_t::line_continuation_semicolon
1164 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1165 : , advgetopt::COMMENT_SHELL
1166 2 : , advgetopt::SECTION_OPERATOR_NONE);
1167 :
1168 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1169 :
1170 1 : CATCH_REQUIRE(setup.is_valid());
1171 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_semicolon);
1172 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1173 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1174 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1175 :
1176 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1177 :
1178 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1179 1 : CATCH_REQUIRE(file->get_errno() == 0);
1180 1 : CATCH_REQUIRE(file->get_sections().empty());
1181 1 : CATCH_REQUIRE(file->get_parameters().size() == 1);
1182 :
1183 1 : CATCH_REQUIRE(file->has_parameter("normal"));
1184 1 : CATCH_REQUIRE_FALSE(file->has_parameter("rfc-822"));
1185 1 : CATCH_REQUIRE_FALSE(file->has_parameter("continue"));
1186 1 : CATCH_REQUIRE_FALSE(file->has_parameter("msdos"));
1187 1 : CATCH_REQUIRE_FALSE(file->has_parameter("and-continue"));
1188 1 : CATCH_REQUIRE_FALSE(file->has_parameter("unix"));
1189 1 : CATCH_REQUIRE_FALSE(file->has_parameter("to-continue"));
1190 1 : CATCH_REQUIRE_FALSE(file->has_parameter("fortran"));
1191 1 : CATCH_REQUIRE_FALSE(file->has_parameter("&since"));
1192 1 : CATCH_REQUIRE_FALSE(file->has_parameter("semicolon"));
1193 1 : CATCH_REQUIRE_FALSE(file->has_parameter("a"));
1194 :
1195 1 : CATCH_REQUIRE(file->get_parameter("normal") == std::string("param\n"
1196 : "\n"
1197 : "rfc-822=start here\n"
1198 : " continue=there\n"
1199 : "\n"
1200 : "msdos=end with &\n"
1201 : " and-continue=on next line\n"
1202 : "\n"
1203 : "unix=end with \\\n"
1204 : "to-continue=like this\n"
1205 : "\n"
1206 : "fortran=fortran is funny\n"
1207 : "&since=it starts with an & on the following line\n"
1208 : "\n"
1209 : "semicolon=this ends with\n"
1210 : "a=semi-colon only"));
1211 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == std::string());
1212 1 : CATCH_REQUIRE(file->get_parameter("continue") == std::string());
1213 1 : CATCH_REQUIRE(file->get_parameter("msdos") == std::string());
1214 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == std::string());
1215 1 : CATCH_REQUIRE(file->get_parameter("unix") == std::string());
1216 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == std::string());
1217 1 : CATCH_REQUIRE(file->get_parameter("fortran") == std::string());
1218 1 : CATCH_REQUIRE(file->get_parameter("&since") == std::string());
1219 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == std::string());
1220 1 : CATCH_REQUIRE(file->get_parameter("a") == std::string());
1221 : }
1222 : CATCH_END_SECTION()
1223 6 : }
1224 :
1225 :
1226 :
1227 6 : CATCH_TEST_CASE("config_assignment_operator_tests", "[config][getopt][valid]")
1228 : {
1229 8 : CATCH_START_SECTION("equal")
1230 : {
1231 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("assignment-operator", "equal");
1232 :
1233 : {
1234 2 : std::ofstream config_file;
1235 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1236 1 : CATCH_REQUIRE(config_file.good());
1237 1 : config_file <<
1238 : "# Auto-generated\n"
1239 : "equal=value\n"
1240 : "\n"
1241 : "name_value=127\n"
1242 : "\n"
1243 : "and=no operator\n"
1244 : ;
1245 : }
1246 :
1247 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1248 : , advgetopt::line_continuation_t::line_continuation_single_line
1249 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1250 : , advgetopt::COMMENT_SHELL
1251 2 : , advgetopt::SECTION_OPERATOR_NONE);
1252 :
1253 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1254 :
1255 1 : CATCH_REQUIRE(setup.is_valid());
1256 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1257 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1258 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1259 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1260 :
1261 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1262 :
1263 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1264 1 : CATCH_REQUIRE(file->get_errno() == 0);
1265 1 : CATCH_REQUIRE(file->get_sections().empty());
1266 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1267 :
1268 1 : CATCH_REQUIRE(file->has_parameter("equal"));
1269 1 : CATCH_REQUIRE(file->has_parameter("name-value"));
1270 1 : CATCH_REQUIRE(file->has_parameter("and"));
1271 :
1272 1 : CATCH_REQUIRE(file->get_parameter("equal") == "value");
1273 1 : CATCH_REQUIRE(file->get_parameter("name-value") == "127");
1274 1 : CATCH_REQUIRE(file->get_parameter("and") == "no operator");
1275 : }
1276 : CATCH_END_SECTION()
1277 :
1278 8 : CATCH_START_SECTION("colon")
1279 : {
1280 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("assignment-operator", "colon");
1281 :
1282 : {
1283 2 : std::ofstream config_file;
1284 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1285 1 : CATCH_REQUIRE(config_file.good());
1286 1 : config_file <<
1287 : "# Auto-generated\n"
1288 : "equal_value\n"
1289 : "\n"
1290 : "name:value=127\n"
1291 : "\n"
1292 : "and_no-operator\n"
1293 : ;
1294 : }
1295 :
1296 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1297 : , advgetopt::line_continuation_t::line_continuation_single_line
1298 : , advgetopt::ASSIGNMENT_OPERATOR_COLON
1299 : , advgetopt::COMMENT_SHELL
1300 2 : , advgetopt::SECTION_OPERATOR_NONE);
1301 :
1302 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1303 :
1304 1 : CATCH_REQUIRE(setup.is_valid());
1305 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1306 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_COLON);
1307 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1308 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1309 :
1310 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1311 :
1312 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1313 1 : CATCH_REQUIRE(file->get_errno() == 0);
1314 1 : CATCH_REQUIRE(file->get_sections().empty());
1315 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1316 :
1317 1 : CATCH_REQUIRE(file->has_parameter("equal-value"));
1318 1 : CATCH_REQUIRE(file->has_parameter("name"));
1319 1 : CATCH_REQUIRE(file->has_parameter("and-no-operator"));
1320 :
1321 1 : CATCH_REQUIRE(file->get_parameter("equal-value") == std::string());
1322 1 : CATCH_REQUIRE(file->get_parameter("name") == "value=127");
1323 1 : CATCH_REQUIRE(file->get_parameter("and-no-operator") == std::string());
1324 : }
1325 : CATCH_END_SECTION()
1326 :
1327 8 : CATCH_START_SECTION("space")
1328 : {
1329 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("assignment-operator", "space");
1330 :
1331 : {
1332 2 : std::ofstream config_file;
1333 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1334 1 : CATCH_REQUIRE(config_file.good());
1335 1 : config_file <<
1336 : "# Auto-generated\n"
1337 : "equal-value\n"
1338 : "\n"
1339 : "name 127\n"
1340 : "\n"
1341 : "and-no operator\n"
1342 : ;
1343 : }
1344 :
1345 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1346 : , advgetopt::line_continuation_t::line_continuation_single_line
1347 : , advgetopt::ASSIGNMENT_OPERATOR_SPACE
1348 : , advgetopt::COMMENT_SHELL
1349 2 : , advgetopt::SECTION_OPERATOR_NONE);
1350 :
1351 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1352 :
1353 1 : CATCH_REQUIRE(setup.is_valid());
1354 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1355 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_SPACE);
1356 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1357 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1358 :
1359 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1360 :
1361 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1362 1 : CATCH_REQUIRE(file->get_errno() == 0);
1363 1 : CATCH_REQUIRE(file->get_sections().empty());
1364 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1365 :
1366 1 : CATCH_REQUIRE(file->has_parameter("equal-value"));
1367 1 : CATCH_REQUIRE(file->has_parameter("name"));
1368 1 : CATCH_REQUIRE(file->has_parameter("and-no"));
1369 :
1370 1 : CATCH_REQUIRE(file->get_parameter("equal-value") == std::string());
1371 1 : CATCH_REQUIRE(file->get_parameter("name") == "127");
1372 1 : CATCH_REQUIRE(file->get_parameter("and-no") == "operator");
1373 : }
1374 : CATCH_END_SECTION()
1375 :
1376 8 : CATCH_START_SECTION("equal_colon_and_space")
1377 : {
1378 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("assignment-operator", "all");
1379 :
1380 : {
1381 2 : std::ofstream config_file;
1382 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1383 1 : CATCH_REQUIRE(config_file.good());
1384 1 : config_file <<
1385 : "# Auto-generated\n"
1386 : "equal=value\n"
1387 : "\n"
1388 : "name: 127\n"
1389 : "\n"
1390 : "and no operator\n"
1391 : ;
1392 : }
1393 :
1394 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1395 : , advgetopt::line_continuation_t::line_continuation_single_line
1396 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1397 : | advgetopt::ASSIGNMENT_OPERATOR_COLON
1398 : | advgetopt::ASSIGNMENT_OPERATOR_SPACE
1399 : , advgetopt::COMMENT_SHELL
1400 2 : , advgetopt::SECTION_OPERATOR_NONE);
1401 :
1402 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1403 :
1404 1 : CATCH_REQUIRE(setup.is_valid());
1405 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1406 1 : CATCH_REQUIRE(setup.get_assignment_operator() == (advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1407 : | advgetopt::ASSIGNMENT_OPERATOR_COLON
1408 : | advgetopt::ASSIGNMENT_OPERATOR_SPACE));
1409 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1410 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1411 :
1412 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1413 :
1414 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1415 1 : CATCH_REQUIRE(file->get_errno() == 0);
1416 1 : CATCH_REQUIRE(file->get_sections().empty());
1417 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1418 :
1419 1 : CATCH_REQUIRE(file->has_parameter("equal"));
1420 1 : CATCH_REQUIRE(file->has_parameter("name"));
1421 1 : CATCH_REQUIRE(file->has_parameter("and"));
1422 :
1423 1 : CATCH_REQUIRE(file->get_parameter("equal") == "value");
1424 1 : CATCH_REQUIRE(file->get_parameter("name") == "127");
1425 1 : CATCH_REQUIRE(file->get_parameter("and") == "no operator");
1426 : }
1427 : CATCH_END_SECTION()
1428 4 : }
1429 :
1430 :
1431 :
1432 :
1433 :
1434 6 : CATCH_TEST_CASE("config_comment_tests", "[config][getopt][valid]")
1435 : {
1436 8 : CATCH_START_SECTION("ini comment")
1437 : {
1438 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("comment", "ini");
1439 :
1440 : {
1441 2 : std::ofstream config_file;
1442 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1443 1 : CATCH_REQUIRE(config_file.good());
1444 1 : config_file <<
1445 : "; Auto-generated\n"
1446 : "ini=comment\n"
1447 : ";ignore=this one\n"
1448 : "is=the semi-colon\n"
1449 : ";continuation=with Unix\\\n"
1450 : "also=works for\\\n"
1451 : "comments\n"
1452 : ;
1453 : }
1454 :
1455 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1456 : , advgetopt::line_continuation_t::line_continuation_unix
1457 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1458 : , advgetopt::COMMENT_INI
1459 2 : , advgetopt::SECTION_OPERATOR_NONE);
1460 :
1461 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1462 :
1463 1 : CATCH_REQUIRE(setup.is_valid());
1464 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1465 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1466 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_INI);
1467 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1468 :
1469 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1470 :
1471 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1472 1 : CATCH_REQUIRE(file->get_errno() == 0);
1473 1 : CATCH_REQUIRE(file->get_sections().empty());
1474 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
1475 :
1476 1 : CATCH_REQUIRE(file->has_parameter("ini"));
1477 1 : CATCH_REQUIRE(file->has_parameter("is"));
1478 :
1479 1 : CATCH_REQUIRE(file->get_parameter("ini") == "comment");
1480 1 : CATCH_REQUIRE(file->get_parameter("is") == "the semi-colon");
1481 : }
1482 : CATCH_END_SECTION()
1483 :
1484 8 : CATCH_START_SECTION("shell comment")
1485 : {
1486 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("comment", "shell");
1487 :
1488 : {
1489 2 : std::ofstream config_file;
1490 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1491 1 : CATCH_REQUIRE(config_file.good());
1492 1 : config_file <<
1493 : "# Auto-generated\n"
1494 : "shell=comment\n"
1495 : "#ignore=this one\n"
1496 : "is=the hash (`#`) character\n"
1497 : "#continuation=with Unix\\\n"
1498 : "also=works for\\\n"
1499 : "comments\n"
1500 : ;
1501 : }
1502 :
1503 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1504 : , advgetopt::line_continuation_t::line_continuation_unix
1505 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1506 : , advgetopt::COMMENT_SHELL
1507 2 : , advgetopt::SECTION_OPERATOR_NONE);
1508 :
1509 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1510 :
1511 1 : CATCH_REQUIRE(setup.is_valid());
1512 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1513 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1514 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1515 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1516 :
1517 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1518 :
1519 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1520 1 : CATCH_REQUIRE(file->get_errno() == 0);
1521 1 : CATCH_REQUIRE(file->get_sections().empty());
1522 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
1523 :
1524 1 : CATCH_REQUIRE(file->has_parameter("shell"));
1525 1 : CATCH_REQUIRE(file->has_parameter("is"));
1526 :
1527 1 : CATCH_REQUIRE(file->get_parameter("shell") == "comment");
1528 1 : CATCH_REQUIRE(file->get_parameter("is") == "the hash (`#`) character");
1529 : }
1530 : CATCH_END_SECTION()
1531 :
1532 8 : CATCH_START_SECTION("C++ comment")
1533 : {
1534 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("comment", "cpp");
1535 :
1536 : {
1537 2 : std::ofstream config_file;
1538 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1539 1 : CATCH_REQUIRE(config_file.good());
1540 1 : config_file <<
1541 : "// Auto-generated\n"
1542 : "cpp=comment\n"
1543 : "//ignore=this one\n"
1544 : "is=the double slash (`//`)\n"
1545 : "//continuation=with Unix\\\n"
1546 : "also=works for\\\n"
1547 : "comments\n"
1548 : ;
1549 : }
1550 :
1551 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1552 : , advgetopt::line_continuation_t::line_continuation_unix
1553 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1554 : , advgetopt::COMMENT_CPP
1555 2 : , advgetopt::SECTION_OPERATOR_NONE);
1556 :
1557 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1558 :
1559 1 : CATCH_REQUIRE(setup.is_valid());
1560 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1561 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1562 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_CPP);
1563 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1564 :
1565 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1566 :
1567 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1568 1 : CATCH_REQUIRE(file->get_errno() == 0);
1569 1 : CATCH_REQUIRE(file->get_sections().empty());
1570 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
1571 :
1572 1 : CATCH_REQUIRE(file->has_parameter("cpp"));
1573 1 : CATCH_REQUIRE(file->has_parameter("is"));
1574 :
1575 1 : CATCH_REQUIRE(file->get_parameter("cpp") == "comment");
1576 1 : CATCH_REQUIRE(file->get_parameter("is") == "the double slash (`//`)");
1577 : }
1578 : CATCH_END_SECTION()
1579 :
1580 8 : CATCH_START_SECTION("All three comments")
1581 : {
1582 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("comment", "all-comments");
1583 :
1584 : {
1585 2 : std::ofstream config_file;
1586 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1587 1 : CATCH_REQUIRE(config_file.good());
1588 1 : config_file <<
1589 : "// Auto-generated\n"
1590 : "all=comments\n"
1591 : ";ignore=this one\n"
1592 : "together=for powerful config support\n"
1593 : "#continuation=with Unix\\\n"
1594 : "also=works for\\\n"
1595 : "comments\n"
1596 : "but=maybe\n"
1597 : ";we=should\\\n"
1598 : "test=continuation\n"
1599 : "//with=each\\\n"
1600 : "each=type of comment\n"
1601 : ;
1602 : }
1603 :
1604 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1605 : , advgetopt::line_continuation_t::line_continuation_unix
1606 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1607 : , advgetopt::COMMENT_INI | advgetopt::COMMENT_SHELL | advgetopt::COMMENT_CPP
1608 2 : , advgetopt::SECTION_OPERATOR_NONE);
1609 :
1610 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1611 :
1612 1 : CATCH_REQUIRE(setup.is_valid());
1613 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1614 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1615 1 : CATCH_REQUIRE(setup.get_comment() == (advgetopt::COMMENT_INI | advgetopt::COMMENT_SHELL | advgetopt::COMMENT_CPP));
1616 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1617 :
1618 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1619 :
1620 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1621 1 : CATCH_REQUIRE(file->get_errno() == 0);
1622 1 : CATCH_REQUIRE(file->get_sections().empty());
1623 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1624 :
1625 1 : CATCH_REQUIRE(file->has_parameter("all"));
1626 1 : CATCH_REQUIRE(file->has_parameter("together"));
1627 1 : CATCH_REQUIRE(file->has_parameter("but"));
1628 :
1629 1 : CATCH_REQUIRE(file->get_parameter("all") == "comments");
1630 1 : CATCH_REQUIRE(file->get_parameter("together") == "for powerful config support");
1631 1 : CATCH_REQUIRE(file->get_parameter("but") == "maybe");
1632 : }
1633 : CATCH_END_SECTION()
1634 4 : }
1635 :
1636 :
1637 :
1638 :
1639 :
1640 9 : CATCH_TEST_CASE("config_section_tests", "[config][getopt][valid]")
1641 : {
1642 14 : CATCH_START_SECTION("section operator c (.)")
1643 : {
1644 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-c");
1645 :
1646 : {
1647 2 : std::ofstream config_file;
1648 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1649 1 : CATCH_REQUIRE(config_file.good());
1650 1 : config_file <<
1651 : "# Auto-generated\n"
1652 : "a=color\n"
1653 : "a.b=red\n"
1654 : "a.b.c=122\n"
1655 : "m=size\n"
1656 : "z=edge\n"
1657 : "z.b=line\n"
1658 : "z.b.c=12.72\n"
1659 : ;
1660 : }
1661 :
1662 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1663 : , advgetopt::line_continuation_t::line_continuation_unix
1664 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1665 : , advgetopt::COMMENT_SHELL
1666 2 : , advgetopt::SECTION_OPERATOR_C);
1667 :
1668 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1669 :
1670 1 : CATCH_REQUIRE(setup.is_valid());
1671 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1672 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1673 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1674 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
1675 :
1676 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1677 :
1678 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1679 1 : CATCH_REQUIRE(file->get_errno() == 0);
1680 :
1681 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1682 1 : CATCH_REQUIRE(sections.size() == 4);
1683 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1684 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
1685 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1686 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
1687 :
1688 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
1689 :
1690 1 : CATCH_REQUIRE(file->has_parameter("a"));
1691 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1692 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
1693 1 : CATCH_REQUIRE(file->has_parameter("m"));
1694 1 : CATCH_REQUIRE(file->has_parameter("z"));
1695 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
1696 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
1697 :
1698 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
1699 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1700 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "122");
1701 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
1702 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
1703 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
1704 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
1705 : }
1706 : CATCH_END_SECTION()
1707 :
1708 14 : CATCH_START_SECTION("section operator c++ (::)")
1709 : {
1710 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-cpp");
1711 :
1712 : {
1713 2 : std::ofstream config_file;
1714 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1715 1 : CATCH_REQUIRE(config_file.good());
1716 1 : config_file <<
1717 : "# Auto-generated\n"
1718 : "a=color\n"
1719 : "a::b=red\n"
1720 : "a::b::c=122\n"
1721 : "m=size\n"
1722 : "z=edge\n"
1723 : "z::b=line\n"
1724 : "z::b::c=12.72\n"
1725 : ;
1726 : }
1727 :
1728 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1729 : , advgetopt::line_continuation_t::line_continuation_unix
1730 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1731 : , advgetopt::COMMENT_SHELL
1732 2 : , advgetopt::SECTION_OPERATOR_CPP);
1733 :
1734 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1735 :
1736 1 : CATCH_REQUIRE(setup.is_valid());
1737 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1738 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1739 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1740 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_CPP);
1741 :
1742 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1743 :
1744 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1745 1 : CATCH_REQUIRE(file->get_errno() == 0);
1746 :
1747 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1748 1 : CATCH_REQUIRE(sections.size() == 4);
1749 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1750 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
1751 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1752 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
1753 :
1754 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
1755 :
1756 1 : CATCH_REQUIRE(file->has_parameter("a"));
1757 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1758 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
1759 1 : CATCH_REQUIRE(file->has_parameter("m"));
1760 1 : CATCH_REQUIRE(file->has_parameter("z"));
1761 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
1762 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
1763 :
1764 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
1765 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1766 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "122");
1767 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
1768 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
1769 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
1770 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
1771 : }
1772 : CATCH_END_SECTION()
1773 :
1774 14 : CATCH_START_SECTION("section operator block ({ ... })")
1775 : {
1776 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-block");
1777 :
1778 : {
1779 2 : std::ofstream config_file;
1780 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1781 1 : CATCH_REQUIRE(config_file.good());
1782 1 : config_file <<
1783 : "# Auto-generated\n"
1784 : "a=color\n"
1785 : "a {\n"
1786 : " b=red\n"
1787 : " b {\n"
1788 : " c=122\n"
1789 : " }\n"
1790 : "}\n"
1791 : "m=size\n"
1792 : "z=edge\n"
1793 : "z {\n"
1794 : " b {\n"
1795 : " c=12.72\n"
1796 : " }\n"
1797 : " b=line\n"
1798 : "}\n"
1799 : ;
1800 : }
1801 :
1802 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1803 : , advgetopt::line_continuation_t::line_continuation_unix
1804 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1805 : , advgetopt::COMMENT_SHELL
1806 2 : , advgetopt::SECTION_OPERATOR_BLOCK);
1807 :
1808 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1809 :
1810 1 : CATCH_REQUIRE(setup.is_valid());
1811 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1812 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1813 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1814 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_BLOCK);
1815 :
1816 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1817 :
1818 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1819 1 : CATCH_REQUIRE(file->get_errno() == 0);
1820 :
1821 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1822 1 : CATCH_REQUIRE(sections.size() == 4);
1823 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1824 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
1825 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1826 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
1827 :
1828 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
1829 :
1830 1 : CATCH_REQUIRE(file->has_parameter("a"));
1831 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1832 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
1833 1 : CATCH_REQUIRE(file->has_parameter("m"));
1834 1 : CATCH_REQUIRE(file->has_parameter("z"));
1835 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
1836 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
1837 :
1838 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
1839 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1840 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "122");
1841 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
1842 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
1843 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
1844 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
1845 : }
1846 : CATCH_END_SECTION()
1847 :
1848 14 : CATCH_START_SECTION("section operator ini file ([...])")
1849 : {
1850 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-ini-file");
1851 :
1852 : {
1853 2 : std::ofstream config_file;
1854 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1855 1 : CATCH_REQUIRE(config_file.good());
1856 1 : config_file <<
1857 : "# Auto-generated\n"
1858 : "a=color\n"
1859 : "[a]\n"
1860 : "b=red\n"
1861 : "b-c=122\n"
1862 : "[]\n"
1863 : "m=size\n"
1864 : "z=edge\n"
1865 : "[z] # we allow comments here\n"
1866 : "b=line\n"
1867 : "b-c=12.72\n"
1868 : "[p]#nospacenecessary\n"
1869 : "b=comment\n"
1870 : "b-c=allowed\n"
1871 : ;
1872 : }
1873 :
1874 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1875 : , advgetopt::line_continuation_t::line_continuation_unix
1876 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1877 : , advgetopt::COMMENT_SHELL
1878 2 : , advgetopt::SECTION_OPERATOR_INI_FILE);
1879 :
1880 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1881 :
1882 1 : CATCH_REQUIRE(setup.is_valid());
1883 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1884 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1885 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1886 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_INI_FILE);
1887 :
1888 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1889 :
1890 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1891 1 : CATCH_REQUIRE(file->get_errno() == 0);
1892 :
1893 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1894 1 : CATCH_REQUIRE(sections.size() == 3);
1895 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1896 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1897 1 : CATCH_REQUIRE(sections.find("p") != sections.end());
1898 :
1899 1 : CATCH_REQUIRE(file->get_parameters().size() == 9);
1900 :
1901 1 : CATCH_REQUIRE(file->has_parameter("a"));
1902 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1903 1 : CATCH_REQUIRE(file->has_parameter("a::b-c"));
1904 1 : CATCH_REQUIRE(file->has_parameter("m"));
1905 1 : CATCH_REQUIRE(file->has_parameter("z"));
1906 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
1907 1 : CATCH_REQUIRE(file->has_parameter("z::b-c"));
1908 1 : CATCH_REQUIRE(file->has_parameter("p::b"));
1909 1 : CATCH_REQUIRE(file->has_parameter("p::b-c"));
1910 :
1911 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
1912 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1913 1 : CATCH_REQUIRE(file->get_parameter("a::b-c") == "122");
1914 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
1915 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
1916 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
1917 1 : CATCH_REQUIRE(file->get_parameter("z::b-c") == "12.72");
1918 1 : CATCH_REQUIRE(file->get_parameter("p::b") == "comment");
1919 1 : CATCH_REQUIRE(file->get_parameter("p::b-c") == "allowed");
1920 : }
1921 : CATCH_END_SECTION()
1922 :
1923 14 : CATCH_START_SECTION("section operator ini-file & c++")
1924 : {
1925 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-double");
1926 :
1927 : {
1928 2 : std::ofstream config_file;
1929 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1930 1 : CATCH_REQUIRE(config_file.good());
1931 1 : config_file <<
1932 : "# Auto-generated\n"
1933 : "[a]\n"
1934 : "b=red\n"
1935 : "b::c=209\n"
1936 : "::h=high\n"
1937 : "m=size\n"
1938 : "[z]\n"
1939 : "z=edge\n"
1940 : "::b=line\n"
1941 : "z::b::c=17.92\n"
1942 : ;
1943 : }
1944 :
1945 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1946 : , advgetopt::line_continuation_t::line_continuation_unix
1947 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1948 : , advgetopt::COMMENT_SHELL
1949 2 : , advgetopt::SECTION_OPERATOR_INI_FILE | advgetopt::SECTION_OPERATOR_CPP);
1950 :
1951 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
1952 :
1953 1 : CATCH_REQUIRE(setup.is_valid());
1954 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1955 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1956 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1957 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_INI_FILE | advgetopt::SECTION_OPERATOR_CPP));
1958 :
1959 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1960 :
1961 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1962 1 : CATCH_REQUIRE(file->get_errno() == 0);
1963 :
1964 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1965 1 : CATCH_REQUIRE(sections.size() == 4);
1966 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1967 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
1968 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1969 1 : CATCH_REQUIRE(sections.find("z::z::b") != sections.end());
1970 :
1971 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
1972 :
1973 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1974 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
1975 1 : CATCH_REQUIRE(file->has_parameter("h"));
1976 1 : CATCH_REQUIRE(file->has_parameter("a::m"));
1977 1 : CATCH_REQUIRE(file->has_parameter("z::z"));
1978 1 : CATCH_REQUIRE(file->has_parameter("b"));
1979 1 : CATCH_REQUIRE(file->has_parameter("z::z::b::c"));
1980 :
1981 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1982 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "209");
1983 1 : CATCH_REQUIRE(file->get_parameter("h") == "high");
1984 1 : CATCH_REQUIRE(file->get_parameter("a::m") == "size");
1985 1 : CATCH_REQUIRE(file->get_parameter("z::z") == "edge");
1986 1 : CATCH_REQUIRE(file->get_parameter("b") == "line");
1987 1 : CATCH_REQUIRE(file->get_parameter("z::z::b::c") == "17.92");
1988 : }
1989 : CATCH_END_SECTION()
1990 :
1991 14 : CATCH_START_SECTION("section of variables ([variables])")
1992 : {
1993 : // in a config file variables are not auto-managed
1994 : //
1995 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-variables", "section-with-variables");
1996 :
1997 : {
1998 2 : std::ofstream config_file;
1999 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2000 1 : CATCH_REQUIRE(config_file.good());
2001 1 : config_file <<
2002 : "# Auto-generated\n"
2003 : "edge=${blue}\n"
2004 : "background=${white}\n"
2005 : "foreground=${black}\n"
2006 : "[error]\n"
2007 : "edge=${red}\n"
2008 : "background=${gray}\n"
2009 : "[variables]\n"
2010 : "red=\"#ff0000\"\n"
2011 : "green=\"#00ff00\"\n"
2012 : "blue=\"#0000ff\"\n"
2013 : "no_color=\"#000000\"\n"
2014 : "black=${no_color}\n"
2015 : "white=\"#ffffff\"\n"
2016 : "gray=\"#aaaaaa\"\n"
2017 : ;
2018 : }
2019 :
2020 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2021 : , advgetopt::line_continuation_t::line_continuation_unix
2022 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2023 : , advgetopt::COMMENT_SHELL
2024 2 : , advgetopt::SECTION_OPERATOR_INI_FILE);
2025 :
2026 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
2027 :
2028 1 : CATCH_REQUIRE(setup.is_valid());
2029 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2030 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2031 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2032 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_INI_FILE);
2033 :
2034 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2035 :
2036 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2037 1 : CATCH_REQUIRE(file->get_errno() == 0);
2038 :
2039 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2040 1 : CATCH_REQUIRE(sections.size() == 2);
2041 1 : CATCH_REQUIRE(sections.find("error") != sections.end());
2042 1 : CATCH_REQUIRE(sections.find("variables") != sections.end());
2043 :
2044 1 : CATCH_REQUIRE(file->get_parameters().size() == 12);
2045 :
2046 1 : CATCH_REQUIRE(file->has_parameter("edge"));
2047 1 : CATCH_REQUIRE(file->has_parameter("background"));
2048 1 : CATCH_REQUIRE(file->has_parameter("foreground"));
2049 1 : CATCH_REQUIRE(file->has_parameter("error::edge"));
2050 1 : CATCH_REQUIRE(file->has_parameter("error::background"));
2051 1 : CATCH_REQUIRE(file->has_parameter("variables::red"));
2052 1 : CATCH_REQUIRE(file->has_parameter("variables::green"));
2053 1 : CATCH_REQUIRE(file->has_parameter("variables::blue"));
2054 1 : CATCH_REQUIRE(file->has_parameter("variables::no_color"));
2055 1 : CATCH_REQUIRE(file->has_parameter("variables::black"));
2056 1 : CATCH_REQUIRE(file->has_parameter("variables::white"));
2057 1 : CATCH_REQUIRE(file->has_parameter("variables::gray"));
2058 :
2059 : // without a variables attached, we get the raw (original) data back
2060 : //
2061 1 : CATCH_REQUIRE(file->get_parameter("edge") == "${blue}");
2062 1 : CATCH_REQUIRE(file->get_parameter("background") == "${white}");
2063 1 : CATCH_REQUIRE(file->get_parameter("foreground") == "${black}");
2064 1 : CATCH_REQUIRE(file->get_parameter("error::edge") == "${red}");
2065 1 : CATCH_REQUIRE(file->get_parameter("error::background") == "${gray}");
2066 1 : CATCH_REQUIRE(file->get_parameter("variables::red") == "#ff0000");
2067 1 : CATCH_REQUIRE(file->get_parameter("variables::green") == "#00ff00");
2068 1 : CATCH_REQUIRE(file->get_parameter("variables::blue") == "#0000ff");
2069 1 : CATCH_REQUIRE(file->get_parameter("variables::no_color") == "#000000");
2070 1 : CATCH_REQUIRE(file->get_parameter("variables::black") == "${no_color}");
2071 1 : CATCH_REQUIRE(file->get_parameter("variables::white") == "#ffffff");
2072 1 : CATCH_REQUIRE(file->get_parameter("variables::gray") == "#aaaaaa");
2073 :
2074 : // transform the "[variables]" section to variables
2075 : //
2076 2 : advgetopt::variables::pointer_t vars(std::make_shared<advgetopt::variables>());
2077 1 : CATCH_REQUIRE(file->section_to_variables("variables", vars) == 7);
2078 1 : file->set_variables(vars);
2079 1 : CATCH_REQUIRE(file->get_variables() == vars);
2080 :
2081 1 : sections = file->get_sections();
2082 1 : CATCH_REQUIRE(sections.size() == 1);
2083 1 : CATCH_REQUIRE(sections.find("error") != sections.end());
2084 1 : CATCH_REQUIRE(sections.find("variables") == sections.end());
2085 :
2086 1 : CATCH_REQUIRE(file->get_parameters().size() == 5);
2087 :
2088 1 : CATCH_REQUIRE(file->has_parameter("edge"));
2089 1 : CATCH_REQUIRE(file->has_parameter("background"));
2090 1 : CATCH_REQUIRE(file->has_parameter("foreground"));
2091 1 : CATCH_REQUIRE(file->has_parameter("error::edge"));
2092 1 : CATCH_REQUIRE(file->has_parameter("error::background"));
2093 1 : CATCH_REQUIRE_FALSE(file->has_parameter("variables::red"));
2094 1 : CATCH_REQUIRE_FALSE(file->has_parameter("variables::green"));
2095 1 : CATCH_REQUIRE_FALSE(file->has_parameter("variables::blue"));
2096 1 : CATCH_REQUIRE_FALSE(file->has_parameter("variables::no_color"));
2097 1 : CATCH_REQUIRE_FALSE(file->has_parameter("variables::black"));
2098 1 : CATCH_REQUIRE_FALSE(file->has_parameter("variables::white"));
2099 1 : CATCH_REQUIRE_FALSE(file->has_parameter("variables::gray"));
2100 :
2101 1 : CATCH_REQUIRE(file->get_parameter("edge") == "#0000ff");
2102 1 : CATCH_REQUIRE(file->get_parameter("background") == "#ffffff");
2103 1 : CATCH_REQUIRE(file->get_parameter("foreground") == "#000000");
2104 1 : CATCH_REQUIRE(file->get_parameter("error::edge") == "#ff0000");
2105 1 : CATCH_REQUIRE(file->get_parameter("error::background") == "#aaaaaa");
2106 : }
2107 : CATCH_END_SECTION()
2108 :
2109 14 : CATCH_START_SECTION("command line with .conf including section of variables ([variables])")
2110 : {
2111 : // in a config file variables are not auto-managed
2112 : //
2113 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("command-line-and-section-variables", "command-section-with-variables");
2114 :
2115 : {
2116 2 : std::ofstream config_file;
2117 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2118 1 : CATCH_REQUIRE(config_file.good());
2119 1 : config_file <<
2120 : "# Auto-generated\n"
2121 : "edge=${blue}\n"
2122 : "background=${white}\n"
2123 : "foreground=${black}\n"
2124 : "[error]\n"
2125 : "edge=${red}\n"
2126 : "background=${gray}\n"
2127 : "[variables]\n"
2128 : "red=\"#ff0000\"\n"
2129 : "green=\"#00ff00\"\n"
2130 : "blue=\"#0000ff\"\n"
2131 : "no_color=\"#000000\"\n"
2132 : "black=${no_color}\n"
2133 : "orange=\"#80ff00\"\n"
2134 : "white=\"#ffffff\"\n"
2135 : "gray=\"#aaaaaa\"\n"
2136 : ;
2137 : }
2138 :
2139 1 : const advgetopt::option options[] =
2140 : {
2141 : advgetopt::define_option(
2142 : advgetopt::Name("edge")
2143 : , advgetopt::Flags(advgetopt::all_flags<
2144 : advgetopt::GETOPT_FLAG_REQUIRED
2145 : , advgetopt::GETOPT_FLAG_PROCESS_VARIABLES>())
2146 : ),
2147 : advgetopt::define_option(
2148 : advgetopt::Name("background")
2149 : , advgetopt::Flags(advgetopt::all_flags<
2150 : advgetopt::GETOPT_FLAG_REQUIRED
2151 : , advgetopt::GETOPT_FLAG_PROCESS_VARIABLES>())
2152 : ),
2153 : advgetopt::define_option(
2154 : advgetopt::Name("foreground")
2155 : , advgetopt::Flags(advgetopt::all_flags<
2156 : advgetopt::GETOPT_FLAG_REQUIRED
2157 : , advgetopt::GETOPT_FLAG_PROCESS_VARIABLES>())
2158 : ),
2159 : advgetopt::define_option(
2160 : advgetopt::Name("error::edge")
2161 : , advgetopt::Flags(advgetopt::all_flags<
2162 : advgetopt::GETOPT_FLAG_REQUIRED
2163 : , advgetopt::GETOPT_FLAG_PROCESS_VARIABLES>())
2164 : ),
2165 : advgetopt::define_option(
2166 : advgetopt::Name("error::background")
2167 : , advgetopt::Flags(advgetopt::all_flags<
2168 : advgetopt::GETOPT_FLAG_REQUIRED
2169 : , advgetopt::GETOPT_FLAG_PROCESS_VARIABLES>())
2170 : ),
2171 : advgetopt::define_option(
2172 : advgetopt::Name("error::foreground")
2173 : , advgetopt::Flags(advgetopt::all_flags<
2174 : advgetopt::GETOPT_FLAG_REQUIRED
2175 : , advgetopt::GETOPT_FLAG_PROCESS_VARIABLES>())
2176 : ),
2177 : advgetopt::define_option(
2178 : advgetopt::Name("see-config")
2179 : , advgetopt::Flags(advgetopt::standalone_command_flags<>())
2180 : ),
2181 : advgetopt::end_options()
2182 : };
2183 :
2184 1 : char const * const configuration_files[] =
2185 : {
2186 1 : SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(),
2187 : nullptr
2188 1 : };
2189 :
2190 1 : advgetopt::options_environment environment_options;
2191 1 : environment_options.f_project_name = "unittest";
2192 1 : environment_options.f_options = options;
2193 1 : environment_options.f_help_header = "Usage: configuration with variables through environment.";
2194 1 : environment_options.f_section_variables_name = "variables";
2195 1 : environment_options.f_configuration_files = configuration_files;
2196 :
2197 1 : char const * cargv[] =
2198 : {
2199 : "/usr/bin/cmd-n-config",
2200 : "--see-config",
2201 : "--error::foreground",
2202 : "${orange}",
2203 : nullptr
2204 : };
2205 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
2206 1 : char ** argv = const_cast<char **>(cargv);
2207 :
2208 2 : advgetopt::getopt::pointer_t opts(std::make_shared<advgetopt::getopt>(environment_options, argc, argv));
2209 1 : CATCH_REQUIRE(opts != nullptr);
2210 :
2211 2 : advgetopt::variables::pointer_t variables(opts->get_variables());
2212 1 : CATCH_REQUIRE(variables != nullptr);
2213 :
2214 1 : CATCH_REQUIRE(opts->is_defined("see-config"));
2215 1 : CATCH_REQUIRE(opts->is_defined("edge"));
2216 1 : CATCH_REQUIRE(opts->is_defined("background"));
2217 1 : CATCH_REQUIRE(opts->is_defined("foreground"));
2218 1 : CATCH_REQUIRE(opts->is_defined("error::edge"));
2219 1 : CATCH_REQUIRE(opts->is_defined("error::background"));
2220 1 : CATCH_REQUIRE(opts->is_defined("error::foreground"));
2221 1 : CATCH_REQUIRE_FALSE(opts->is_defined("variables::red"));
2222 1 : CATCH_REQUIRE_FALSE(opts->is_defined("variables::green"));
2223 1 : CATCH_REQUIRE_FALSE(opts->is_defined("variables::blue"));
2224 1 : CATCH_REQUIRE_FALSE(opts->is_defined("variables::no_color"));
2225 1 : CATCH_REQUIRE_FALSE(opts->is_defined("variables::black"));
2226 1 : CATCH_REQUIRE_FALSE(opts->is_defined("variables::orange"));
2227 1 : CATCH_REQUIRE_FALSE(opts->is_defined("variables::white"));
2228 1 : CATCH_REQUIRE_FALSE(opts->is_defined("variables::gray"));
2229 :
2230 1 : CATCH_REQUIRE(opts->get_string("edge") == "#0000ff");
2231 1 : CATCH_REQUIRE(opts->get_string("background") == "#ffffff");
2232 1 : CATCH_REQUIRE(opts->get_string("foreground") == "#000000");
2233 1 : CATCH_REQUIRE(opts->get_string("error::edge") == "#ff0000");
2234 1 : CATCH_REQUIRE(opts->get_string("error::background") == "#aaaaaa");
2235 1 : CATCH_REQUIRE(opts->get_string("error::foreground") == "#80ff00");
2236 :
2237 1 : CATCH_REQUIRE(opts->get_option("edge")->get_variables() == variables);
2238 1 : CATCH_REQUIRE(opts->get_option("background")->get_variables() == variables);
2239 1 : CATCH_REQUIRE(opts->get_option("foreground")->get_variables() == variables);
2240 1 : CATCH_REQUIRE(opts->get_option("error::edge")->get_variables() == variables);
2241 1 : CATCH_REQUIRE(opts->get_option("error::background")->get_variables() == variables);
2242 1 : CATCH_REQUIRE(opts->get_option("error::foreground")->get_variables() == variables);
2243 : }
2244 : CATCH_END_SECTION()
2245 7 : }
2246 :
2247 :
2248 :
2249 :
2250 5 : CATCH_TEST_CASE("save_config_file", "[config][getopt][valid]")
2251 : {
2252 6 : CATCH_START_SECTION("load update save (=)")
2253 : {
2254 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("save-operation", "configuration-equal");
2255 :
2256 : {
2257 2 : std::ofstream config_file;
2258 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2259 1 : CATCH_REQUIRE(config_file.good());
2260 1 : config_file <<
2261 : "# Auto-generated\n"
2262 : "a=color\n"
2263 : "b=red\n"
2264 : "call-flag=122\n"
2265 : ;
2266 : }
2267 :
2268 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2269 : , advgetopt::line_continuation_t::line_continuation_single_line
2270 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2271 : , advgetopt::COMMENT_SHELL
2272 2 : , advgetopt::SECTION_OPERATOR_NONE);
2273 :
2274 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
2275 :
2276 1 : CATCH_REQUIRE(setup.is_valid());
2277 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
2278 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2279 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2280 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2281 :
2282 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2283 :
2284 1 : CATCH_REQUIRE(file->exists());
2285 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2286 1 : CATCH_REQUIRE(file->get_errno() == 0);
2287 :
2288 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2289 1 : CATCH_REQUIRE(sections.empty());
2290 :
2291 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
2292 :
2293 1 : CATCH_REQUIRE(file->has_parameter("a"));
2294 1 : CATCH_REQUIRE(file->has_parameter("b"));
2295 1 : CATCH_REQUIRE(file->has_parameter("call-flag"));
2296 :
2297 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2298 1 : CATCH_REQUIRE(file->get_parameter("b") == "red");
2299 1 : CATCH_REQUIRE(file->get_parameter("call-flag") == "122");
2300 :
2301 1 : CATCH_REQUIRE(file->save_configuration());
2302 :
2303 : // no backup since there was no modification so the save did nothing
2304 : //
2305 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".bak").c_str(), F_OK) != 0);
2306 :
2307 1 : file->set_parameter(std::string(), "a", "size");
2308 1 : file->set_parameter(std::string(), "b", "tall");
2309 1 : file->set_parameter(std::string(), "call-flag", "1920");
2310 :
2311 1 : CATCH_REQUIRE(file->save_configuration());
2312 :
2313 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".bak").c_str(), F_OK) == 0);
2314 :
2315 1 : file->set_parameter(std::string(), "a", "pace");
2316 1 : file->set_parameter(std::string(), "b", "fall");
2317 1 : file->set_parameter(std::string(), "call-flag", "2019");
2318 :
2319 1 : CATCH_REQUIRE(file->save_configuration("save"));
2320 :
2321 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".save").c_str(), F_OK) == 0);
2322 :
2323 2 : std::string const new_name(SNAP_CATCH2_NAMESPACE::g_config_filename + ".conf2");
2324 1 : rename(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), new_name.c_str());
2325 :
2326 1 : advgetopt::conf_file_setup setup2(new_name
2327 : , advgetopt::line_continuation_t::line_continuation_single_line
2328 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2329 : , advgetopt::COMMENT_SHELL
2330 2 : , advgetopt::SECTION_OPERATOR_NONE);
2331 :
2332 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
2333 :
2334 1 : CATCH_REQUIRE(setup2.is_valid());
2335 1 : CATCH_REQUIRE(setup2.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
2336 1 : CATCH_REQUIRE(setup2.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2337 1 : CATCH_REQUIRE(setup2.get_comment() == advgetopt::COMMENT_SHELL);
2338 1 : CATCH_REQUIRE(setup2.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2339 :
2340 2 : advgetopt::conf_file::pointer_t file2(advgetopt::conf_file::get_conf_file(setup2));
2341 :
2342 1 : CATCH_REQUIRE(file2->exists());
2343 1 : CATCH_REQUIRE(file2->get_setup().get_config_url() == setup2.get_config_url());
2344 1 : CATCH_REQUIRE(file2->get_errno() == 0);
2345 :
2346 1 : CATCH_REQUIRE(file->get_sections().empty());
2347 :
2348 1 : CATCH_REQUIRE(file2->get_parameters().size() == 3);
2349 :
2350 1 : CATCH_REQUIRE(file2->has_parameter("a"));
2351 1 : CATCH_REQUIRE(file2->has_parameter("b"));
2352 1 : CATCH_REQUIRE(file2->has_parameter("call-flag"));
2353 :
2354 1 : CATCH_REQUIRE(file2->get_parameter("a") == "pace");
2355 1 : CATCH_REQUIRE(file2->get_parameter("b") == "fall");
2356 1 : CATCH_REQUIRE(file2->get_parameter("call-flag") == "2019");
2357 : }
2358 : CATCH_END_SECTION()
2359 :
2360 6 : CATCH_START_SECTION("load update save (:)")
2361 : {
2362 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("save-operation", "configuration-colon");
2363 :
2364 : {
2365 2 : std::ofstream config_file;
2366 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2367 1 : CATCH_REQUIRE(config_file.good());
2368 1 : config_file <<
2369 : "# Auto-generated\n"
2370 : "a: color\n"
2371 : "b: red\n"
2372 : "call-flag: 122\n"
2373 : ;
2374 : }
2375 :
2376 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2377 : , advgetopt::line_continuation_t::line_continuation_single_line
2378 : , advgetopt::ASSIGNMENT_OPERATOR_COLON
2379 : , advgetopt::COMMENT_SHELL
2380 : , advgetopt::SECTION_OPERATOR_NONE
2381 2 : , advgetopt::NAME_SEPARATOR_DASHES);
2382 :
2383 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
2384 :
2385 1 : CATCH_REQUIRE(setup.is_valid());
2386 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
2387 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_COLON);
2388 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2389 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2390 :
2391 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2392 :
2393 1 : CATCH_REQUIRE(file->exists());
2394 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2395 1 : CATCH_REQUIRE(file->get_errno() == 0);
2396 :
2397 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2398 1 : CATCH_REQUIRE(sections.empty());
2399 :
2400 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
2401 :
2402 1 : CATCH_REQUIRE(file->has_parameter("a"));
2403 1 : CATCH_REQUIRE(file->has_parameter("b"));
2404 1 : CATCH_REQUIRE(file->has_parameter("call-flag"));
2405 :
2406 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2407 1 : CATCH_REQUIRE(file->get_parameter("b") == "red");
2408 1 : CATCH_REQUIRE(file->get_parameter("call-flag") == "122");
2409 :
2410 1 : CATCH_REQUIRE(file->save_configuration());
2411 :
2412 : // no backup since there was no modification so the save did nothing
2413 : //
2414 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".bak").c_str(), F_OK) != 0);
2415 :
2416 1 : file->set_parameter(std::string(), "a", "size");
2417 1 : file->set_parameter(std::string(), "b", "tall");
2418 1 : file->set_parameter(std::string(), "call-flag", "1920");
2419 :
2420 1 : CATCH_REQUIRE(file->save_configuration());
2421 :
2422 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".bak").c_str(), F_OK) == 0);
2423 :
2424 1 : file->set_parameter(std::string(), "a", "pace");
2425 1 : file->set_parameter(std::string(), "b", "fall");
2426 1 : file->set_parameter(std::string(), "call-flag", "2019");
2427 :
2428 1 : CATCH_REQUIRE(file->save_configuration("save"));
2429 :
2430 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".save").c_str(), F_OK) == 0);
2431 :
2432 2 : std::string const new_name(SNAP_CATCH2_NAMESPACE::g_config_filename + ".conf2");
2433 1 : rename(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), new_name.c_str());
2434 :
2435 1 : advgetopt::conf_file_setup setup2(new_name
2436 : , advgetopt::line_continuation_t::line_continuation_single_line
2437 : , advgetopt::ASSIGNMENT_OPERATOR_COLON
2438 : , advgetopt::COMMENT_SHELL
2439 : , advgetopt::SECTION_OPERATOR_NONE
2440 2 : , advgetopt::NAME_SEPARATOR_DASHES);
2441 :
2442 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
2443 :
2444 1 : CATCH_REQUIRE(setup2.is_valid());
2445 1 : CATCH_REQUIRE(setup2.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
2446 1 : CATCH_REQUIRE(setup2.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_COLON);
2447 1 : CATCH_REQUIRE(setup2.get_comment() == advgetopt::COMMENT_SHELL);
2448 1 : CATCH_REQUIRE(setup2.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2449 :
2450 2 : advgetopt::conf_file::pointer_t file2(advgetopt::conf_file::get_conf_file(setup2));
2451 :
2452 1 : CATCH_REQUIRE(file2->exists());
2453 1 : CATCH_REQUIRE(file2->get_setup().get_config_url() == setup2.get_config_url());
2454 1 : CATCH_REQUIRE(file2->get_errno() == 0);
2455 :
2456 1 : CATCH_REQUIRE(file->get_sections().empty());
2457 :
2458 1 : CATCH_REQUIRE(file2->get_parameters().size() == 3);
2459 :
2460 1 : CATCH_REQUIRE(file2->has_parameter("a"));
2461 1 : CATCH_REQUIRE(file2->has_parameter("b"));
2462 1 : CATCH_REQUIRE(file2->has_parameter("call-flag"));
2463 :
2464 1 : CATCH_REQUIRE(file2->get_parameter("a") == "pace");
2465 1 : CATCH_REQUIRE(file2->get_parameter("b") == "fall");
2466 1 : CATCH_REQUIRE(file2->get_parameter("call-flag") == "2019");
2467 : }
2468 : CATCH_END_SECTION()
2469 :
2470 6 : CATCH_START_SECTION("load update save ( )")
2471 : {
2472 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("save-operation", "configuration-space");
2473 :
2474 : {
2475 2 : std::ofstream config_file;
2476 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2477 1 : CATCH_REQUIRE(config_file.good());
2478 1 : config_file <<
2479 : "# This comment is kept along the a= variable\n"
2480 : "a color\n"
2481 : "b red\n"
2482 : "call-flag 122\n"
2483 : ;
2484 : }
2485 :
2486 1 : advgetopt::comment_t const comment(advgetopt::COMMENT_SHELL | advgetopt::COMMENT_SAVE);
2487 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2488 : , advgetopt::line_continuation_t::line_continuation_single_line
2489 : , advgetopt::ASSIGNMENT_OPERATOR_SPACE
2490 : , comment
2491 : , advgetopt::SECTION_OPERATOR_NONE
2492 2 : , advgetopt::NAME_SEPARATOR_DASHES);
2493 :
2494 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
2495 :
2496 1 : CATCH_REQUIRE(setup.is_valid());
2497 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
2498 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_SPACE);
2499 1 : CATCH_REQUIRE(setup.get_comment() == comment);
2500 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2501 :
2502 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2503 :
2504 1 : CATCH_REQUIRE(file->exists());
2505 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2506 1 : CATCH_REQUIRE(file->get_errno() == 0);
2507 :
2508 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2509 1 : CATCH_REQUIRE(sections.empty());
2510 :
2511 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
2512 :
2513 1 : CATCH_REQUIRE(file->has_parameter("a"));
2514 1 : CATCH_REQUIRE(file->has_parameter("b"));
2515 1 : CATCH_REQUIRE(file->has_parameter("call-flag"));
2516 :
2517 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2518 1 : CATCH_REQUIRE(file->get_parameter("b") == "red");
2519 1 : CATCH_REQUIRE(file->get_parameter("call-flag") == "122");
2520 :
2521 2 : advgetopt::conf_file::parameters_t params(file->get_parameters());
2522 1 : auto it(params.find("a"));
2523 1 : CATCH_REQUIRE(it != params.end());
2524 1 : CATCH_REQUIRE(it->second.get_comment() == "# This comment is kept along the a= variable\n");
2525 1 : CATCH_REQUIRE(it->second.get_comment(true) == "# This comment is kept along the a= variable\n");
2526 :
2527 1 : it->second.set_comment("# Changing the comment");
2528 1 : CATCH_REQUIRE(it->second.get_comment() == "# Changing the comment");
2529 1 : CATCH_REQUIRE(it->second.get_comment(true) == "# Changing the comment\n");
2530 :
2531 1 : CATCH_REQUIRE(file->save_configuration());
2532 :
2533 : // no backup since there was no modification so the save did nothing
2534 : //
2535 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".bak").c_str(), F_OK) != 0);
2536 :
2537 1 : file->set_parameter(std::string(), "a", "size");
2538 1 : file->set_parameter(std::string(), "b", "tall");
2539 1 : file->set_parameter(std::string(), "call-flag", "1920");
2540 :
2541 1 : CATCH_REQUIRE(file->save_configuration());
2542 :
2543 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".bak").c_str(), F_OK) == 0);
2544 :
2545 1 : file->set_parameter(std::string(), "a", "pace");
2546 1 : file->set_parameter(std::string(), "b", "fall");
2547 1 : file->set_parameter(std::string(), "call-flag", "2019");
2548 :
2549 1 : it->second.set_value("warning"); // WARNING: the parameters_t is a copy so you can't change the parameters that way
2550 1 : CATCH_REQUIRE(it->second.get_value() == "warning");
2551 1 : CATCH_REQUIRE(file->get_parameter("a") == "pace");
2552 :
2553 : // the following constructor and assignment are defined although not
2554 : // used within the library at the moment
2555 : //
2556 2 : advgetopt::parameter_value const value("other value");
2557 1 : it->second = value;
2558 1 : CATCH_REQUIRE(it->second.get_value() == "other value");
2559 1 : CATCH_REQUIRE(file->get_parameter("a") == "pace");
2560 :
2561 1 : CATCH_REQUIRE(file->save_configuration("save"));
2562 :
2563 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".save").c_str(), F_OK) == 0);
2564 :
2565 2 : std::string const new_name(SNAP_CATCH2_NAMESPACE::g_config_filename + ".conf2");
2566 1 : rename(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), new_name.c_str());
2567 :
2568 1 : advgetopt::conf_file_setup setup2(new_name
2569 : , advgetopt::line_continuation_t::line_continuation_single_line
2570 : , advgetopt::ASSIGNMENT_OPERATOR_SPACE
2571 : , comment
2572 : , advgetopt::SECTION_OPERATOR_NONE
2573 2 : , advgetopt::NAME_SEPARATOR_DASHES);
2574 :
2575 1 : CATCH_REQUIRE(setup.get_original_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
2576 :
2577 1 : CATCH_REQUIRE(setup2.is_valid());
2578 1 : CATCH_REQUIRE(setup2.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
2579 1 : CATCH_REQUIRE(setup2.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_SPACE);
2580 1 : CATCH_REQUIRE(setup2.get_comment() == comment);
2581 1 : CATCH_REQUIRE(setup2.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2582 :
2583 2 : advgetopt::conf_file::pointer_t file2(advgetopt::conf_file::get_conf_file(setup2));
2584 :
2585 1 : CATCH_REQUIRE(file2->exists());
2586 1 : CATCH_REQUIRE(file2->get_setup().get_config_url() == setup2.get_config_url());
2587 1 : CATCH_REQUIRE(file2->get_errno() == 0);
2588 :
2589 1 : CATCH_REQUIRE(file->get_sections().empty());
2590 :
2591 1 : CATCH_REQUIRE(file2->get_parameters().size() == 3);
2592 :
2593 1 : CATCH_REQUIRE(file2->has_parameter("a"));
2594 1 : CATCH_REQUIRE(file2->has_parameter("b"));
2595 1 : CATCH_REQUIRE(file2->has_parameter("call-flag"));
2596 :
2597 1 : CATCH_REQUIRE(file2->get_parameter("a") == "pace");
2598 1 : CATCH_REQUIRE(file2->get_parameter("b") == "fall");
2599 1 : CATCH_REQUIRE(file2->get_parameter("call-flag") == "2019");
2600 :
2601 1 : file2->erase_all_parameters();
2602 1 : CATCH_REQUIRE_FALSE(file2->has_parameter("a"));
2603 1 : CATCH_REQUIRE_FALSE(file2->has_parameter("b"));
2604 1 : CATCH_REQUIRE_FALSE(file2->has_parameter("call-flag"));
2605 : }
2606 : CATCH_END_SECTION()
2607 3 : }
2608 :
2609 :
2610 :
2611 :
2612 :
2613 :
2614 :
2615 4 : CATCH_TEST_CASE("invalid_configuration_setup", "[config][getopt][invalid]")
2616 : {
2617 4 : CATCH_START_SECTION("Empty Filename")
2618 : {
2619 1 : CATCH_REQUIRE_THROWS_MATCHES(
2620 : advgetopt::conf_file_setup(
2621 : std::string()
2622 : , static_cast<advgetopt::line_continuation_t>(rand())
2623 : , rand()
2624 : , rand()
2625 : , rand())
2626 : , advgetopt::getopt_invalid
2627 : , Catch::Matchers::ExceptionMessage(
2628 : "getopt_exception: trying to load a configuration file using an empty filename."));
2629 : }
2630 : CATCH_END_SECTION()
2631 :
2632 4 : CATCH_START_SECTION("Invalid Line Continuation")
2633 : {
2634 6 : for(int count(0); count < 5; ++count)
2635 : {
2636 5 : advgetopt::line_continuation_t lc(advgetopt::line_continuation_t::line_continuation_unix);
2637 0 : do
2638 : {
2639 5 : lc = static_cast<advgetopt::line_continuation_t>(rand());
2640 : }
2641 : while(lc >= advgetopt::line_continuation_t::line_continuation_single_line
2642 5 : && lc <= advgetopt::line_continuation_t::line_continuation_semicolon);
2643 :
2644 5 : advgetopt::conf_file_setup setup(
2645 : "/etc/advgetopt/system.conf"
2646 : , lc // <- this is invalid
2647 5 : , rand() & advgetopt::ASSIGNMENT_OPERATOR_MASK
2648 5 : , rand() & advgetopt::COMMENT_MASK
2649 20 : , rand() & advgetopt::SECTION_OPERATOR_MASK);
2650 :
2651 5 : CATCH_REQUIRE(setup.is_valid());
2652 :
2653 5 : CATCH_REQUIRE_THROWS_MATCHES(
2654 : setup.get_config_url()
2655 : , advgetopt::getopt_logic_error
2656 : , Catch::Matchers::ExceptionMessage(
2657 : "getopt_logic_error: unexpected line continuation."));
2658 : }
2659 : }
2660 : CATCH_END_SECTION()
2661 2 : }
2662 :
2663 :
2664 :
2665 :
2666 :
2667 :
2668 :
2669 3 : CATCH_TEST_CASE("config_reload_invalid_setup", "[config][getopt][invalid]")
2670 : {
2671 2 : CATCH_START_SECTION("Load a file, update it, verify it does not get reloaded")
2672 : {
2673 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-reload", "load-twice-wrong-parameters");
2674 :
2675 : {
2676 2 : std::ofstream config_file;
2677 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2678 1 : CATCH_REQUIRE(config_file.good());
2679 1 : config_file <<
2680 : "# Auto-generated\n"
2681 : "duplicates=work\n"
2682 : "varying=parameters\n"
2683 : "however=is\n"
2684 : "not=valid\n"
2685 : ;
2686 : }
2687 :
2688 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2689 : , advgetopt::line_continuation_t::line_continuation_single_line
2690 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2691 : , advgetopt::COMMENT_SHELL
2692 2 : , advgetopt::SECTION_OPERATOR_NONE);
2693 :
2694 1 : CATCH_REQUIRE(setup.is_valid());
2695 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
2696 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2697 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2698 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2699 :
2700 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2701 :
2702 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2703 1 : CATCH_REQUIRE(file->get_errno() == 0);
2704 1 : CATCH_REQUIRE(file->get_sections().empty());
2705 1 : CATCH_REQUIRE(file->get_parameters().size() == 4);
2706 :
2707 1 : CATCH_REQUIRE(file->has_parameter("duplicates"));
2708 1 : CATCH_REQUIRE(file->has_parameter("varying"));
2709 1 : CATCH_REQUIRE(file->has_parameter("however"));
2710 1 : CATCH_REQUIRE(file->has_parameter("not"));
2711 :
2712 1 : CATCH_REQUIRE(file->get_parameter("duplicates") == "work");
2713 1 : CATCH_REQUIRE(file->get_parameter("varying") == "parameters");
2714 1 : CATCH_REQUIRE(file->get_parameter("however") == "is");
2715 1 : CATCH_REQUIRE(file->get_parameter("not") == "valid");
2716 :
2717 : // "reloading" that very same file but with the "wrong" parameters
2718 : // fails
2719 : //
2720 7 : for(int lc(static_cast<int>(advgetopt::line_continuation_t::line_continuation_single_line));
2721 7 : lc <= static_cast<int>(advgetopt::line_continuation_t::line_continuation_semicolon);
2722 : ++lc)
2723 : {
2724 6 : if(static_cast<advgetopt::line_continuation_t>(lc) == advgetopt::line_continuation_t::line_continuation_single_line)
2725 : {
2726 1 : continue;
2727 : }
2728 :
2729 45 : for(advgetopt::assignment_operator_t ao(0);
2730 45 : ao <= advgetopt::ASSIGNMENT_OPERATOR_MASK;
2731 : ++ao)
2732 : {
2733 40 : if(ao == advgetopt::ASSIGNMENT_OPERATOR_EQUAL)
2734 : {
2735 5 : continue;
2736 : }
2737 :
2738 280 : for(advgetopt::comment_t c(0);
2739 280 : c < advgetopt::COMMENT_MASK;
2740 : ++c)
2741 : {
2742 245 : if(c == advgetopt::COMMENT_SHELL)
2743 : {
2744 35 : continue;
2745 : }
2746 :
2747 3360 : for(advgetopt::section_operator_t so(0);
2748 3360 : so < advgetopt::SECTION_OPERATOR_MASK;
2749 : ++so)
2750 : {
2751 3150 : if(c == advgetopt::SECTION_OPERATOR_NONE)
2752 : {
2753 525 : continue;
2754 : }
2755 :
2756 2625 : advgetopt::conf_file_setup different_setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2757 : , static_cast<advgetopt::line_continuation_t>(lc)
2758 : , ao
2759 : , c
2760 5250 : , so);
2761 :
2762 2625 : CATCH_REQUIRE_THROWS_MATCHES(
2763 : advgetopt::conf_file::get_conf_file(different_setup)
2764 : , advgetopt::getopt_logic_error
2765 : , Catch::Matchers::ExceptionMessage(
2766 : "getopt_logic_error: trying to load configuration file \""
2767 : + different_setup.get_config_url()
2768 : + "\" but an existing configuration file with the same name was loaded with URL: \""
2769 : + setup.get_config_url()
2770 : + "\"."));
2771 : }
2772 : }
2773 : }
2774 : }
2775 : }
2776 : CATCH_END_SECTION()
2777 1 : }
2778 :
2779 :
2780 3 : CATCH_TEST_CASE("missing_configuration_file", "[config][getopt][invalid]")
2781 : {
2782 2 : CATCH_START_SECTION("Create a conf_file without the file")
2783 : {
2784 6 : for(int count(0); count < 5; ++count)
2785 : {
2786 5 : int const id(rand());
2787 10 : std::string const name("delete-file-" + std::to_string(id));
2788 :
2789 5 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("delete", name);
2790 :
2791 : {
2792 10 : std::ofstream config_file;
2793 5 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2794 5 : CATCH_REQUIRE(config_file.good());
2795 5 : config_file <<
2796 : "# Auto-generated\n"
2797 : "param=optional\n"
2798 : ;
2799 : }
2800 :
2801 : // create the setup while the file still exists
2802 : //
2803 5 : advgetopt::conf_file_setup setup(
2804 : SNAP_CATCH2_NAMESPACE::g_config_filename
2805 : , advgetopt::line_continuation_t::line_continuation_unix
2806 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2807 : , advgetopt::COMMENT_SHELL
2808 10 : , advgetopt::SECTION_OPERATOR_NONE);
2809 :
2810 : // get the full name before the unlink()
2811 10 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
2812 :
2813 : // now unlink() that file
2814 : //
2815 5 : unlink(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str());
2816 :
2817 : // still valid since we do not check again after the
2818 : // constructor ran
2819 : //
2820 5 : CATCH_REQUIRE(setup.is_valid());
2821 5 : CATCH_REQUIRE(setup.get_filename() == fn.get());
2822 5 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2823 5 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2824 5 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2825 5 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2826 :
2827 : // so when trying to create the conf_file object it fails
2828 : // opening the file
2829 : //
2830 10 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2831 5 : CATCH_REQUIRE(file->get_errno() == ENOENT);
2832 5 : CATCH_REQUIRE_FALSE(file->exists());
2833 : }
2834 : }
2835 : CATCH_END_SECTION()
2836 1 : }
2837 :
2838 :
2839 11 : CATCH_TEST_CASE("invalid_sections", "[config][getopt][invalid]")
2840 : {
2841 18 : CATCH_START_SECTION("variable name cannot start with a period when C operator is active")
2842 : {
2843 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "period-name");
2844 :
2845 : {
2846 2 : std::ofstream config_file;
2847 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2848 1 : CATCH_REQUIRE(config_file.good());
2849 1 : config_file <<
2850 : "# Auto-generated\n"
2851 : "a=color\n"
2852 : "a..b=red\n"
2853 : ".a.b.c=122\n"
2854 : "m=size\n"
2855 : "z=edge\n"
2856 : "z.b=line\n"
2857 : "z..b.c=12.72\n"
2858 : ;
2859 : }
2860 :
2861 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2862 : , advgetopt::line_continuation_t::line_continuation_unix
2863 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2864 : , advgetopt::COMMENT_SHELL
2865 2 : , advgetopt::SECTION_OPERATOR_C);
2866 :
2867 1 : CATCH_REQUIRE(setup.is_valid());
2868 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2869 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2870 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2871 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
2872 :
2873 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2874 : "error: option name \".a.b.c\" cannot start with"
2875 : " a period (.).");
2876 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2877 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2878 :
2879 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2880 1 : CATCH_REQUIRE(file->get_errno() == 0);
2881 :
2882 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2883 1 : CATCH_REQUIRE(sections.size() == 3);
2884 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
2885 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
2886 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
2887 :
2888 1 : CATCH_REQUIRE(file->get_parameters().size() == 6);
2889 :
2890 1 : CATCH_REQUIRE(file->has_parameter("a"));
2891 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
2892 1 : CATCH_REQUIRE(file->has_parameter("m"));
2893 1 : CATCH_REQUIRE(file->has_parameter("z"));
2894 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
2895 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
2896 :
2897 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2898 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
2899 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
2900 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
2901 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
2902 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
2903 : }
2904 : CATCH_END_SECTION()
2905 :
2906 18 : CATCH_START_SECTION("two section operators one after another can cause trouble")
2907 : {
2908 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "name-period-cpp-name");
2909 :
2910 : {
2911 2 : std::ofstream config_file;
2912 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2913 1 : CATCH_REQUIRE(config_file.good());
2914 1 : config_file <<
2915 : "# Auto-generated\n"
2916 : "a=color\n"
2917 : "a..b=red\n"
2918 : "a.::b.c=122\n"
2919 : "m=size\n"
2920 : "z=edge\n"
2921 : "z.b=line\n"
2922 : "z..b.c=12.72\n"
2923 : ;
2924 : }
2925 :
2926 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2927 : , advgetopt::line_continuation_t::line_continuation_unix
2928 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2929 : , advgetopt::COMMENT_SHELL
2930 2 : , advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_CPP);
2931 :
2932 1 : CATCH_REQUIRE(setup.is_valid());
2933 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2934 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2935 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2936 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_CPP));
2937 :
2938 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2939 : "error: option name \"a.::b.c\" cannot start with"
2940 : " a scope operator (::).");
2941 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2942 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2943 :
2944 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2945 1 : CATCH_REQUIRE(file->get_errno() == 0);
2946 :
2947 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2948 1 : CATCH_REQUIRE(sections.size() == 3);
2949 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
2950 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
2951 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
2952 :
2953 1 : CATCH_REQUIRE(file->get_parameters().size() == 6);
2954 :
2955 1 : CATCH_REQUIRE(file->has_parameter("a"));
2956 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
2957 1 : CATCH_REQUIRE(file->has_parameter("m"));
2958 1 : CATCH_REQUIRE(file->has_parameter("z"));
2959 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
2960 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
2961 :
2962 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2963 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
2964 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
2965 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
2966 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
2967 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
2968 : }
2969 : CATCH_END_SECTION()
2970 :
2971 18 : CATCH_START_SECTION("section operator cannot appear at the end")
2972 : {
2973 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "name-period-name-cpp");
2974 :
2975 : {
2976 2 : std::ofstream config_file;
2977 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2978 1 : CATCH_REQUIRE(config_file.good());
2979 1 : config_file <<
2980 : "# Auto-generated\n"
2981 : "a=color\n"
2982 : "a..b=red\n"
2983 : "a.b.c::=122\n"
2984 : "m=size\n"
2985 : "z=edge\n"
2986 : "z.b=line\n"
2987 : "z..b.c=12.72\n"
2988 : ;
2989 : }
2990 :
2991 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2992 : , advgetopt::line_continuation_t::line_continuation_unix
2993 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2994 : , advgetopt::COMMENT_SHELL
2995 2 : , advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_CPP);
2996 :
2997 1 : CATCH_REQUIRE(setup.is_valid());
2998 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2999 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3000 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3001 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_CPP));
3002 :
3003 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3004 : "error: option name \"a.b.c::\" cannot end with a"
3005 : " section operator or be empty.");
3006 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3007 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3008 :
3009 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3010 1 : CATCH_REQUIRE(file->get_errno() == 0);
3011 :
3012 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
3013 1 : CATCH_REQUIRE(sections.size() == 3);
3014 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
3015 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
3016 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
3017 :
3018 1 : CATCH_REQUIRE(file->get_parameters().size() == 6);
3019 :
3020 1 : CATCH_REQUIRE(file->has_parameter("a"));
3021 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
3022 1 : CATCH_REQUIRE(file->has_parameter("m"));
3023 1 : CATCH_REQUIRE(file->has_parameter("z"));
3024 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
3025 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
3026 :
3027 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
3028 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
3029 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
3030 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
3031 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
3032 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
3033 : }
3034 : CATCH_END_SECTION()
3035 :
3036 18 : CATCH_START_SECTION("sections not allowed")
3037 : {
3038 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "section-not-allowed");
3039 :
3040 : {
3041 2 : std::ofstream config_file;
3042 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3043 1 : CATCH_REQUIRE(config_file.good());
3044 1 : config_file <<
3045 : "# Auto-generated\n"
3046 : "a=color\n"
3047 : "a::b=red\n"
3048 : "m.n=size\n"
3049 : "z=edge\n"
3050 : ;
3051 : }
3052 :
3053 : // no errors here since we do not detect the sections in this case
3054 : //
3055 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3056 : , advgetopt::line_continuation_t::line_continuation_unix
3057 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3058 : , advgetopt::COMMENT_SHELL
3059 2 : , advgetopt::SECTION_OPERATOR_NONE);
3060 :
3061 1 : CATCH_REQUIRE(setup.is_valid());
3062 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3063 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3064 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3065 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_NONE));
3066 :
3067 2 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
3068 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3069 : "error: parameter \"a::b\" on line 3 in configuration file \""
3070 2 : + std::string(fn.get())
3071 3 : + "\" includes a character not acceptable for a section or"
3072 : " parameter name (controls, space, quotes, and \";#/=:?+\\\").");
3073 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3074 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3075 :
3076 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3077 1 : CATCH_REQUIRE(file->get_errno() == 0);
3078 :
3079 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
3080 1 : CATCH_REQUIRE(sections.empty());
3081 :
3082 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
3083 :
3084 1 : CATCH_REQUIRE(file->has_parameter("a"));
3085 1 : CATCH_REQUIRE_FALSE(file->has_parameter("a::b"));
3086 1 : CATCH_REQUIRE(file->has_parameter("m.n"));
3087 1 : CATCH_REQUIRE(file->has_parameter("z"));
3088 :
3089 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
3090 1 : CATCH_REQUIRE(file->get_parameter("a::b") == std::string());
3091 1 : CATCH_REQUIRE(file->get_parameter("m.n") == "size");
3092 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
3093 :
3094 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3095 : "error: option name \"blue::shepard\" cannot be added to"
3096 : " section \"j::k\" because there is no section support"
3097 : " for this configuration file.");
3098 1 : file->set_parameter("j::k", "blue::shepard", "2001");
3099 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3100 : }
3101 : CATCH_END_SECTION()
3102 :
3103 18 : CATCH_START_SECTION("invalid characters in names")
3104 : {
3105 1 : std::string const bad_chars(
3106 : "\x01\x02\x03\x04\x05\x06\x07"
3107 : "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
3108 : "\x10\x11\x12\x13\x14\x15\x16\x17"
3109 : "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
3110 : "\x20"
3111 : "'\";#/=:?+\\"
3112 2 : );
3113 43 : for(auto c : bad_chars)
3114 : {
3115 : // white spaces get removed from the line so we cannot test
3116 : // them in this way
3117 : //
3118 42 : if(std::iswspace(c))
3119 : {
3120 6 : continue;
3121 : }
3122 72 : std::string bc;
3123 36 : bc += c;
3124 :
3125 144 : for(int pos(0); pos < 3; ++pos)
3126 : {
3127 216 : std::string spos("undefined");
3128 216 : std::string bad_char("undefined");
3129 108 : switch(pos)
3130 : {
3131 36 : case 0:
3132 36 : spos = "start";
3133 36 : bad_char = bc + "bad-char";
3134 36 : break;
3135 :
3136 36 : case 1:
3137 36 : spos = "middle";
3138 36 : bad_char = "bad" + bc + "char";
3139 36 : break;
3140 :
3141 36 : case 2:
3142 36 : spos = "end";
3143 36 : bad_char = "bad-char" + bc;
3144 36 : break;
3145 :
3146 : }
3147 108 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-characters", "bad-character-" + std::to_string(static_cast<int>(c)) + "-" + spos);
3148 :
3149 : {
3150 216 : std::ofstream config_file;
3151 108 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3152 108 : CATCH_REQUIRE(config_file.good());
3153 108 : char op(c == '=' ? ':' : '=');
3154 : config_file <<
3155 : "good" << op << "red\n"
3156 : << bad_char << op << "color\n" // <-- bad char
3157 108 : "fine" << op << "param\n";
3158 : ;
3159 : }
3160 :
3161 : // no errors here since we do not detect the sections in this case
3162 : //
3163 108 : advgetopt::assignment_operator_t as(c == '='
3164 108 : ? advgetopt::ASSIGNMENT_OPERATOR_COLON
3165 : : advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3166 108 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3167 : , advgetopt::line_continuation_t::line_continuation_unix
3168 : , as
3169 : , advgetopt::COMMENT_NONE
3170 216 : , advgetopt::SECTION_OPERATOR_NONE);
3171 :
3172 108 : CATCH_REQUIRE(setup.is_valid());
3173 108 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3174 108 : CATCH_REQUIRE(setup.get_assignment_operator() == as);
3175 108 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_NONE);
3176 108 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_NONE));
3177 :
3178 216 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
3179 216 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3180 : "error: parameter \""
3181 216 : + bad_char
3182 324 : + "\" on line 2 in configuration file \""
3183 324 : + fn.get()
3184 324 : + "\" includes a character not acceptable for a section or"
3185 : " parameter name (controls, space, quotes, and \";#/=:?+\\\").");
3186 216 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3187 :
3188 108 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3189 108 : CATCH_REQUIRE(file->get_errno() == 0);
3190 :
3191 216 : advgetopt::conf_file::sections_t sections(file->get_sections());
3192 108 : CATCH_REQUIRE(sections.empty());
3193 :
3194 108 : CATCH_REQUIRE(file->get_parameters().size() == 2);
3195 :
3196 108 : CATCH_REQUIRE(file->has_parameter("good"));
3197 108 : CATCH_REQUIRE_FALSE(file->has_parameter(bad_char));
3198 108 : CATCH_REQUIRE(file->has_parameter("fine"));
3199 :
3200 108 : CATCH_REQUIRE(file->get_parameter("good") == "red");
3201 108 : CATCH_REQUIRE(file->get_parameter(bad_char) == std::string());
3202 108 : CATCH_REQUIRE(file->get_parameter("fine") == "param");
3203 : }
3204 : }
3205 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3206 : }
3207 : CATCH_END_SECTION()
3208 :
3209 18 : CATCH_START_SECTION("too many sections")
3210 : {
3211 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "too-many-sections");
3212 :
3213 : {
3214 2 : std::ofstream config_file;
3215 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3216 1 : CATCH_REQUIRE(config_file.good());
3217 1 : config_file <<
3218 : "# Auto-generated\n"
3219 : "a=color\n"
3220 : "a::b=red\n"
3221 : "m.n.o=size\n"
3222 : "z=edge\n"
3223 : ;
3224 : }
3225 :
3226 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3227 : , advgetopt::line_continuation_t::line_continuation_unix
3228 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3229 : , advgetopt::COMMENT_SHELL
3230 2 : , advgetopt::SECTION_OPERATOR_CPP | advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_ONE_SECTION);
3231 :
3232 1 : CATCH_REQUIRE(setup.is_valid());
3233 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3234 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3235 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3236 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_CPP | advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_ONE_SECTION));
3237 :
3238 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3239 : "error: option name \"m.n.o\" cannot be added to section"
3240 : " \"m::n\" because this configuration only accepts one"
3241 : " section level.");
3242 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3243 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3244 :
3245 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3246 1 : CATCH_REQUIRE(file->get_errno() == 0);
3247 :
3248 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
3249 1 : CATCH_REQUIRE(sections.size() == 1);
3250 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
3251 :
3252 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
3253 :
3254 1 : CATCH_REQUIRE(file->has_parameter("a"));
3255 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
3256 1 : CATCH_REQUIRE(file->has_parameter("z"));
3257 :
3258 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
3259 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
3260 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
3261 : }
3262 : CATCH_END_SECTION()
3263 :
3264 18 : CATCH_START_SECTION("all '{' were not closed")
3265 : {
3266 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "unclosed-brackets");
3267 :
3268 : {
3269 2 : std::ofstream config_file;
3270 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3271 1 : CATCH_REQUIRE(config_file.good());
3272 1 : config_file <<
3273 : "# Auto-generated\n"
3274 : "colors {\n"
3275 : " b=red\n"
3276 : " c=blue\n"
3277 : ;
3278 : }
3279 :
3280 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3281 : , advgetopt::line_continuation_t::line_continuation_unix
3282 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3283 : , advgetopt::COMMENT_SHELL
3284 2 : , advgetopt::SECTION_OPERATOR_BLOCK);
3285 :
3286 1 : CATCH_REQUIRE(setup.is_valid());
3287 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3288 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3289 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3290 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_BLOCK);
3291 :
3292 2 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
3293 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3294 : "error: unterminated `section { ... }`, the `}` is missing"
3295 : " in configuration file "
3296 : "\""
3297 2 : + std::string(fn.get())
3298 3 : + "\".");
3299 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3300 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3301 :
3302 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3303 1 : CATCH_REQUIRE(file->get_errno() == 0);
3304 :
3305 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
3306 1 : CATCH_REQUIRE(sections.size() == 1);
3307 1 : CATCH_REQUIRE(sections.find("colors") != sections.end());
3308 :
3309 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
3310 :
3311 1 : CATCH_REQUIRE(file->has_parameter("colors::b"));
3312 1 : CATCH_REQUIRE(file->has_parameter("colors::c"));
3313 :
3314 1 : CATCH_REQUIRE(file->get_parameter("colors::b") == "red");
3315 1 : CATCH_REQUIRE(file->get_parameter("colors::c") == "blue");
3316 : }
3317 : CATCH_END_SECTION()
3318 :
3319 18 : CATCH_START_SECTION("data after ']' in INI file")
3320 : {
3321 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "additional-data");
3322 :
3323 : {
3324 2 : std::ofstream config_file;
3325 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3326 1 : CATCH_REQUIRE(config_file.good());
3327 1 : config_file <<
3328 : "# Auto-generated\n"
3329 : "[colors]\n"
3330 : "b=red\n"
3331 : "c=blue\n"
3332 : "\n"
3333 : "[sizes] comment\n" // <- missing the comment introducer
3334 : "q=1000\n"
3335 : "r=9999\n"
3336 : ;
3337 : }
3338 :
3339 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3340 : , advgetopt::line_continuation_t::line_continuation_unix
3341 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3342 : , advgetopt::COMMENT_SHELL
3343 2 : , advgetopt::SECTION_OPERATOR_INI_FILE);
3344 :
3345 1 : CATCH_REQUIRE(setup.is_valid());
3346 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3347 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3348 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3349 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_INI_FILE);
3350 :
3351 2 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
3352 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3353 : "error: section names in configuration files cannot be followed by anything other than spaces in"
3354 : " \"[sizes] comment\" on line 6 from configuration file \""
3355 2 : + std::string(fn.get())
3356 3 : + "\".");
3357 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3358 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3359 :
3360 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3361 1 : CATCH_REQUIRE(file->get_errno() == 0);
3362 :
3363 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
3364 1 : CATCH_REQUIRE(sections.size() == 1);
3365 1 : CATCH_REQUIRE(sections.find("colors") != sections.end());
3366 :
3367 1 : CATCH_REQUIRE(file->get_parameters().size() == 4);
3368 :
3369 1 : CATCH_REQUIRE(file->has_parameter("colors::b"));
3370 1 : CATCH_REQUIRE(file->has_parameter("colors::c"));
3371 1 : CATCH_REQUIRE(file->has_parameter("colors::q"));
3372 1 : CATCH_REQUIRE(file->has_parameter("colors::r"));
3373 :
3374 1 : CATCH_REQUIRE(file->get_parameter("colors::b") == "red");
3375 1 : CATCH_REQUIRE(file->get_parameter("colors::c") == "blue");
3376 1 : CATCH_REQUIRE(file->get_parameter("colors::q") == "1000");
3377 1 : CATCH_REQUIRE(file->get_parameter("colors::r") == "9999");
3378 : }
3379 : CATCH_END_SECTION()
3380 :
3381 18 : CATCH_START_SECTION("INI file section inside a block is not allowed")
3382 : {
3383 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "ini-inside-block");
3384 :
3385 : {
3386 2 : std::ofstream config_file;
3387 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3388 1 : CATCH_REQUIRE(config_file.good());
3389 1 : config_file <<
3390 : "# Auto-generated\n"
3391 : "[colors]\n"
3392 : "b=red\n"
3393 : "c=blue\n"
3394 : "\n"
3395 : "block {\n"
3396 : " b = block data\n"
3397 : " f = filename\n"
3398 : " [sizes]\n" // <-- INI section inside a block not allowed
3399 : " q=1000\n"
3400 : " r=9999\n"
3401 : "}\n"
3402 : ;
3403 : }
3404 :
3405 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3406 : , advgetopt::line_continuation_t::line_continuation_unix
3407 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3408 : , advgetopt::COMMENT_SHELL
3409 2 : , advgetopt::SECTION_OPERATOR_BLOCK | advgetopt::SECTION_OPERATOR_INI_FILE);
3410 :
3411 1 : CATCH_REQUIRE(setup.is_valid());
3412 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3413 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3414 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3415 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_BLOCK | advgetopt::SECTION_OPERATOR_INI_FILE));
3416 :
3417 2 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
3418 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3419 : "error: `[...]` sections can't be used within a `section"
3420 : " { ... }` on line 9 from configuration file \""
3421 2 : + std::string(fn.get())
3422 3 : + "\".");
3423 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3424 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3425 :
3426 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3427 1 : CATCH_REQUIRE(file->get_errno() == 0);
3428 :
3429 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
3430 1 : CATCH_REQUIRE(sections.size() == 2);
3431 1 : CATCH_REQUIRE(sections.find("colors") != sections.end());
3432 1 : CATCH_REQUIRE(sections.find("colors::block") != sections.end());
3433 :
3434 1 : CATCH_REQUIRE(file->get_parameters().size() == 6);
3435 :
3436 1 : CATCH_REQUIRE(file->has_parameter("colors::b"));
3437 1 : CATCH_REQUIRE(file->has_parameter("colors::c"));
3438 1 : CATCH_REQUIRE(file->has_parameter("colors::block::b"));
3439 1 : CATCH_REQUIRE(file->has_parameter("colors::block::f"));
3440 1 : CATCH_REQUIRE(file->has_parameter("colors::block::q"));
3441 1 : CATCH_REQUIRE(file->has_parameter("colors::block::r"));
3442 :
3443 1 : CATCH_REQUIRE(file->get_parameter("colors::b") == "red");
3444 1 : CATCH_REQUIRE(file->get_parameter("colors::c") == "blue");
3445 1 : CATCH_REQUIRE(file->get_parameter("colors::block::b") == "block data");
3446 1 : CATCH_REQUIRE(file->get_parameter("colors::block::f") == "filename");
3447 1 : CATCH_REQUIRE(file->get_parameter("colors::block::q") == "1000");
3448 1 : CATCH_REQUIRE(file->get_parameter("colors::block::r") == "9999");
3449 : }
3450 : CATCH_END_SECTION()
3451 9 : }
3452 :
3453 :
3454 :
3455 7 : CATCH_TEST_CASE("invalid_variable_name", "[config][getopt][invalid]")
3456 : {
3457 10 : CATCH_START_SECTION("empty variable name")
3458 : {
3459 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "name-missing");
3460 :
3461 : {
3462 2 : std::ofstream config_file;
3463 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3464 1 : CATCH_REQUIRE(config_file.good());
3465 1 : config_file <<
3466 : "# Auto-generated\n"
3467 : "=color\n" // <-- name missing
3468 : "a..b=red\n"
3469 : "a.b.c=142\n"
3470 : ;
3471 : }
3472 :
3473 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3474 : , advgetopt::line_continuation_t::line_continuation_unix
3475 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3476 : , advgetopt::COMMENT_SHELL
3477 2 : , advgetopt::SECTION_OPERATOR_C);
3478 :
3479 1 : CATCH_REQUIRE(setup.is_valid());
3480 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3481 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3482 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3483 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
3484 :
3485 2 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
3486 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3487 : "error: no option name in \"=color\""
3488 : " on line 2 from configuration file \""
3489 2 : + std::string(fn.get())
3490 3 : + "\", missing name before the assignment operator?");
3491 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3492 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3493 :
3494 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3495 1 : CATCH_REQUIRE(file->get_errno() == 0);
3496 :
3497 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
3498 1 : CATCH_REQUIRE(sections.size() == 2);
3499 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
3500 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
3501 :
3502 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
3503 :
3504 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
3505 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
3506 :
3507 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
3508 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "142");
3509 : }
3510 : CATCH_END_SECTION()
3511 :
3512 10 : CATCH_START_SECTION("empty variable name after section name")
3513 : {
3514 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "section-and-name-missing");
3515 :
3516 : {
3517 2 : std::ofstream config_file;
3518 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3519 1 : CATCH_REQUIRE(config_file.good());
3520 1 : config_file <<
3521 : "# Auto-generated\n"
3522 : "a..b=red\n"
3523 : "a.b.=color\n" // <-- name missing after section name
3524 : "a.b.c=142\n"
3525 : ;
3526 : }
3527 :
3528 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3529 : , advgetopt::line_continuation_t::line_continuation_unix
3530 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3531 : , advgetopt::COMMENT_SHELL
3532 2 : , advgetopt::SECTION_OPERATOR_C);
3533 :
3534 1 : CATCH_REQUIRE(setup.is_valid());
3535 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3536 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3537 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3538 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
3539 :
3540 1 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3541 : "error: option name \"a.b.\" cannot end with a section operator or be empty.");
3542 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3543 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3544 :
3545 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3546 1 : CATCH_REQUIRE(file->get_errno() == 0);
3547 :
3548 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
3549 1 : CATCH_REQUIRE(sections.size() == 2);
3550 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
3551 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
3552 :
3553 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
3554 :
3555 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
3556 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
3557 :
3558 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
3559 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "142");
3560 : }
3561 : CATCH_END_SECTION()
3562 :
3563 10 : CATCH_START_SECTION("variable name starts with a dash")
3564 : {
3565 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "dash-name");
3566 :
3567 : {
3568 2 : std::ofstream config_file;
3569 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3570 1 : CATCH_REQUIRE(config_file.good());
3571 1 : config_file <<
3572 : "# Auto-generated\n"
3573 : "a=color\n"
3574 : "-bad-dash=reddish\n" // <-- name starts with '-'
3575 : "size=412\n"
3576 : ;
3577 : }
3578 :
3579 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3580 : , advgetopt::line_continuation_t::line_continuation_unix
3581 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3582 : , advgetopt::COMMENT_SHELL
3583 2 : , advgetopt::SECTION_OPERATOR_C);
3584 :
3585 1 : CATCH_REQUIRE(setup.is_valid());
3586 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3587 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3588 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3589 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
3590 :
3591 2 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
3592 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3593 : "error: option names in configuration files cannot"
3594 : " start with a dash or an underscore in"
3595 : " \"-bad-dash=reddish\" on line 3 from configuration file \""
3596 2 : + std::string(fn.get())
3597 3 : + "\".");
3598 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3599 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3600 :
3601 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3602 1 : CATCH_REQUIRE(file->get_errno() == 0);
3603 :
3604 1 : CATCH_REQUIRE(file->get_sections().empty());
3605 :
3606 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
3607 :
3608 1 : CATCH_REQUIRE(file->has_parameter("a"));
3609 1 : CATCH_REQUIRE(file->has_parameter("size"));
3610 :
3611 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
3612 1 : CATCH_REQUIRE(file->get_parameter("size") == "412");
3613 : }
3614 : CATCH_END_SECTION()
3615 :
3616 10 : CATCH_START_SECTION("variable name starts with an underscore")
3617 : {
3618 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "underscore-name");
3619 :
3620 : {
3621 2 : std::ofstream config_file;
3622 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3623 1 : CATCH_REQUIRE(config_file.good());
3624 1 : config_file <<
3625 : "# Auto-generated\n"
3626 : "a_variable=color\n"
3627 : "_bad_underscore=reddish\n" // <-- name starts with '_'
3628 : "pos_and_size=412x33+32-18\n"
3629 : ;
3630 : }
3631 :
3632 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3633 : , advgetopt::line_continuation_t::line_continuation_unix
3634 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3635 : , advgetopt::COMMENT_SHELL
3636 2 : , advgetopt::SECTION_OPERATOR_C);
3637 :
3638 1 : CATCH_REQUIRE(setup.is_valid());
3639 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3640 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3641 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3642 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
3643 :
3644 2 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
3645 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3646 : "error: option names in configuration files cannot"
3647 : " start with a dash or an underscore in"
3648 : " \"_bad_underscore=reddish\" on line 3 from configuration file \""
3649 2 : + std::string(fn.get())
3650 3 : + "\".");
3651 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3652 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3653 :
3654 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3655 1 : CATCH_REQUIRE(file->get_errno() == 0);
3656 :
3657 1 : CATCH_REQUIRE(file->get_sections().empty());
3658 :
3659 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
3660 :
3661 1 : CATCH_REQUIRE(file->has_parameter("a-variable"));
3662 1 : CATCH_REQUIRE(file->has_parameter("pos-and-size"));
3663 :
3664 1 : CATCH_REQUIRE(file->get_parameter("a-variable") == "color");
3665 1 : CATCH_REQUIRE(file->get_parameter("pos-and-size") == "412x33+32-18");
3666 : }
3667 : CATCH_END_SECTION()
3668 :
3669 10 : CATCH_START_SECTION("variable name with spaces")
3670 : {
3671 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "name-space-more-name");
3672 :
3673 : {
3674 2 : std::ofstream config_file;
3675 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
3676 1 : CATCH_REQUIRE(config_file.good());
3677 1 : config_file <<
3678 : "# Auto-generated\n"
3679 : "a variable=color\n"
3680 : "bad space=reddish\n"
3681 : "pos and size=412x33+32-18\n"
3682 : ;
3683 : }
3684 :
3685 1 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
3686 : , advgetopt::line_continuation_t::line_continuation_unix
3687 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
3688 : , advgetopt::COMMENT_SHELL
3689 2 : , advgetopt::SECTION_OPERATOR_C);
3690 :
3691 1 : CATCH_REQUIRE(setup.is_valid());
3692 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
3693 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
3694 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
3695 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
3696 :
3697 2 : std::unique_ptr<char, decltype(&::free)> fn(realpath(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), nullptr), &::free);
3698 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3699 : "error: option name from \"a variable=color\" on line"
3700 : " 2 in configuration file \""
3701 2 : + std::string(fn.get())
3702 3 : + "\" cannot include a space, missing assignment operator?");
3703 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3704 : "error: option name from \"bad space=reddish\" on line"
3705 : " 3 in configuration file \""
3706 2 : + std::string(fn.get())
3707 3 : + "\" cannot include a space, missing assignment operator?");
3708 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
3709 : "error: option name from \"pos and size=412x33+32-18\" on line"
3710 : " 4 in configuration file \""
3711 2 : + std::string(fn.get())
3712 3 : + "\" cannot include a space, missing assignment operator?");
3713 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3714 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3715 :
3716 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3717 1 : CATCH_REQUIRE(file->get_errno() == 0);
3718 :
3719 1 : CATCH_REQUIRE(file->get_sections().empty());
3720 :
3721 1 : CATCH_REQUIRE(file->get_parameters().empty());
3722 : }
3723 : CATCH_END_SECTION()
3724 11 : }
3725 :
3726 :
3727 :
3728 :
3729 :
3730 : // vim: ts=4 sw=4 et
|