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