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