Line data Source code
1 : /*
2 : * License:
3 : * Copyright (c) 2006-2019 Made to Order Software Corp. All Rights Reserved
4 : *
5 : * https://snapwebsites.org/
6 : * contact@m2osw.com
7 : *
8 : * This program is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU General Public License as published by
10 : * the Free Software Foundation; either version 2 of the License, or
11 : * (at your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License along
19 : * with this program; if not, write to the Free Software Foundation, Inc.,
20 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 : *
22 : * Authors:
23 : * Alexis Wilke alexis@m2osw.com
24 : */
25 :
26 : // self
27 : //
28 : #include "main.h"
29 :
30 : // advgetopt lib
31 : //
32 : #include <advgetopt/conf_file.h>
33 : #include <advgetopt/exception.h>
34 :
35 : // snapdev lib
36 : //
37 : #include <snapdev/safe_setenv.h>
38 : #include <snapdev/tokenize_string.h>
39 :
40 : // C++ lib
41 : //
42 : #include <fstream>
43 :
44 : // C lib
45 : //
46 : #include <unistd.h>
47 :
48 :
49 :
50 :
51 :
52 :
53 :
54 3 : CATCH_TEST_CASE("configuration_spaces", "[config][getopt]")
55 : {
56 2 : CATCH_START_SECTION("Verify Configuration Spaces")
57 1114113 : for(int c(0); c < 0x110000; ++c)
58 : {
59 1114112 : if(c == '\r'
60 1114111 : || c == '\n')
61 : {
62 2 : CATCH_REQUIRE_FALSE(advgetopt::iswspace(c));
63 : }
64 1114110 : else if(std::iswspace(c))
65 : {
66 4 : CATCH_REQUIRE(advgetopt::iswspace(c));
67 : }
68 : else
69 : {
70 1114106 : CATCH_REQUIRE_FALSE(advgetopt::iswspace(c));
71 : }
72 : }
73 : CATCH_END_SECTION()
74 1 : }
75 :
76 :
77 4 : CATCH_TEST_CASE("configuration_setup", "[config][getopt]")
78 : {
79 4 : CATCH_START_SECTION("Check All Setups")
80 : // 5 * 6 * 8 * 8 * 16 = 30720
81 6 : for(int count(0); count < 5; ++count)
82 : {
83 5 : int const id(rand());
84 10 : std::string const name("setup-file-" + std::to_string(id));
85 :
86 5 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("setup", name);
87 :
88 : {
89 10 : std::ofstream config_file;
90 5 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
91 5 : CATCH_REQUIRE(config_file.good());
92 : config_file <<
93 : "# Auto-generated\n"
94 : "param=optional\n"
95 5 : ;
96 : }
97 :
98 35 : for(int lc(static_cast<int>(advgetopt::line_continuation_t::line_continuation_single_line));
99 35 : lc <= static_cast<int>(advgetopt::line_continuation_t::line_continuation_semicolon);
100 : ++lc)
101 : {
102 270 : for(advgetopt::assignment_operator_t ao(0);
103 270 : ao <= advgetopt::ASSIGNMENT_OPERATOR_MASK;
104 : ++ao)
105 : {
106 1920 : for(advgetopt::comment_t c(0);
107 1920 : c < advgetopt::COMMENT_MASK;
108 : ++c)
109 : {
110 26880 : for(advgetopt::section_operator_t so(0);
111 26880 : so < advgetopt::SECTION_OPERATOR_MASK;
112 : ++so)
113 : {
114 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
115 : , static_cast<advgetopt::line_continuation_t>(lc)
116 : , ao
117 : , c
118 50400 : , so);
119 :
120 25200 : advgetopt::assignment_operator_t real_ao(ao == 0 ? advgetopt::ASSIGNMENT_OPERATOR_EQUAL : ao);
121 :
122 25200 : CATCH_REQUIRE(setup.is_valid());
123 25200 : CATCH_REQUIRE(setup.get_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
124 25200 : CATCH_REQUIRE(setup.get_line_continuation() == static_cast<advgetopt::line_continuation_t>(lc));
125 25200 : CATCH_REQUIRE(setup.get_assignment_operator() == real_ao);
126 25200 : CATCH_REQUIRE(setup.get_comment() == c);
127 25200 : CATCH_REQUIRE(setup.get_section_operator() == so);
128 :
129 50400 : std::string const url(setup.get_config_url());
130 : //std::cerr << "+++ " << lc << " / " << ao << " / " << c << " / " << so << " URL [" << url << "]\n";
131 25200 : CATCH_REQUIRE(url.substr(0, 8) == "file:///");
132 :
133 25200 : CATCH_REQUIRE(url.substr(7, SNAP_CATCH2_NAMESPACE::g_config_filename.length()) == SNAP_CATCH2_NAMESPACE::g_config_filename);
134 :
135 25200 : std::string::size_type const qm_pos(url.find('?'));
136 25200 : if(qm_pos == std::string::npos)
137 : {
138 : // must have the defaults in this case
139 : //
140 0 : CATCH_REQUIRE(static_cast<advgetopt::line_continuation_t>(lc) == advgetopt::line_continuation_t::line_continuation_unix);
141 0 : CATCH_REQUIRE(real_ao == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
142 0 : CATCH_REQUIRE(c == (advgetopt::COMMENT_INI | advgetopt::COMMENT_SHELL));
143 0 : CATCH_REQUIRE(so == advgetopt::SECTION_OPERATOR_INI_FILE);
144 : }
145 : else
146 : {
147 50400 : std::string const qs(url.substr(qm_pos + 1));
148 :
149 50400 : std::vector<std::string> strings;
150 25200 : snap::tokenize_string(strings, qs, "&");
151 :
152 25200 : bool def_lc(true);
153 25200 : bool def_ao(true);
154 25200 : bool def_c(true);
155 25200 : bool def_so(true);
156 :
157 112140 : for(auto s : strings)
158 : {
159 86940 : std::string::size_type const eq_pos(s.find('='));
160 86940 : CATCH_REQUIRE(eq_pos != std::string::npos);
161 :
162 173880 : std::string const var_name(s.substr(0, eq_pos));
163 173880 : std::string const var_value(s.substr(eq_pos + 1));
164 :
165 86940 : if(var_name == "line-continuation")
166 : {
167 21000 : def_lc = false;
168 21000 : switch(static_cast<advgetopt::line_continuation_t>(lc))
169 : {
170 : case advgetopt::line_continuation_t::line_continuation_single_line:
171 4200 : CATCH_REQUIRE(var_value == "single-line");
172 4200 : break;
173 :
174 : case advgetopt::line_continuation_t::line_continuation_rfc_822:
175 4200 : CATCH_REQUIRE(var_value == "rfc-822");
176 4200 : break;
177 :
178 : case advgetopt::line_continuation_t::line_continuation_msdos:
179 4200 : CATCH_REQUIRE(var_value == "msdos");
180 4200 : break;
181 :
182 : case advgetopt::line_continuation_t::line_continuation_unix:
183 0 : CATCH_REQUIRE(var_value == "unix");
184 0 : break;
185 :
186 : case advgetopt::line_continuation_t::line_continuation_fortran:
187 4200 : CATCH_REQUIRE(var_value == "fortran");
188 4200 : break;
189 :
190 : case advgetopt::line_continuation_t::line_continuation_semicolon:
191 4200 : CATCH_REQUIRE(var_value == "semi-colon");
192 4200 : break;
193 :
194 : default:
195 0 : CATCH_REQUIRE(("unknown_var_value for \"line-continuation\":" + var_value) == std::string());
196 0 : break;
197 :
198 : }
199 : }
200 65940 : else if(var_name == "assignment-operator")
201 : {
202 18900 : def_ao = false;
203 37800 : std::vector<std::string> operators;
204 18900 : snap::tokenize_string(operators, var_value, ",");
205 :
206 18900 : if((real_ao & advgetopt::ASSIGNMENT_OPERATOR_EQUAL) != 0)
207 : {
208 9450 : auto it(std::find(operators.begin(), operators.end(), "equal"));
209 9450 : CATCH_REQUIRE(it != operators.end());
210 9450 : operators.erase(it);
211 : }
212 18900 : if((real_ao & advgetopt::ASSIGNMENT_OPERATOR_COLON) != 0)
213 : {
214 12600 : auto it(std::find(operators.begin(), operators.end(), "colon"));
215 12600 : CATCH_REQUIRE(it != operators.end());
216 12600 : operators.erase(it);
217 : }
218 18900 : if((real_ao & advgetopt::ASSIGNMENT_OPERATOR_SPACE) != 0)
219 : {
220 12600 : auto it(std::find(operators.begin(), operators.end(), "space"));
221 12600 : CATCH_REQUIRE(it != operators.end());
222 12600 : operators.erase(it);
223 : }
224 :
225 18900 : CATCH_REQUIRE(operators.empty());
226 : }
227 47040 : else if(var_name == "comment")
228 : {
229 25200 : def_c = false;
230 50400 : std::vector<std::string> comments;
231 25200 : snap::tokenize_string(comments, var_value, ",");
232 :
233 25200 : if((c & advgetopt::COMMENT_INI) != 0)
234 : {
235 10800 : auto it(std::find(comments.begin(), comments.end(), "ini"));
236 10800 : CATCH_REQUIRE(it != comments.end());
237 10800 : comments.erase(it);
238 : }
239 25200 : if((c & advgetopt::COMMENT_SHELL) != 0)
240 : {
241 10800 : auto it(std::find(comments.begin(), comments.end(), "shell"));
242 10800 : CATCH_REQUIRE(it != comments.end());
243 10800 : comments.erase(it);
244 : }
245 25200 : if((c & advgetopt::COMMENT_CPP) != 0)
246 : {
247 10800 : auto it(std::find(comments.begin(), comments.end(), "cpp"));
248 10800 : CATCH_REQUIRE(it != comments.end());
249 10800 : comments.erase(it);
250 : }
251 25200 : if(c == advgetopt::COMMENT_NONE)
252 : {
253 3600 : auto it(std::find(comments.begin(), comments.end(), "none"));
254 3600 : CATCH_REQUIRE(it != comments.end());
255 3600 : comments.erase(it);
256 : }
257 :
258 25200 : CATCH_REQUIRE(comments.empty());
259 : }
260 21840 : else if(var_name == "section-operator")
261 : {
262 21840 : def_so = false;
263 43680 : std::vector<std::string> section_operators;
264 21840 : snap::tokenize_string(section_operators, var_value, ",");
265 :
266 21840 : if((so & advgetopt::SECTION_OPERATOR_C) != 0)
267 : {
268 11760 : auto it(std::find(section_operators.begin(), section_operators.end(), "c"));
269 11760 : CATCH_REQUIRE(it != section_operators.end());
270 11760 : section_operators.erase(it);
271 : }
272 21840 : if((so & advgetopt::SECTION_OPERATOR_CPP) != 0)
273 : {
274 11760 : auto it(std::find(section_operators.begin(), section_operators.end(), "cpp"));
275 11760 : CATCH_REQUIRE(it != section_operators.end());
276 11760 : section_operators.erase(it);
277 : }
278 21840 : if((so & advgetopt::SECTION_OPERATOR_BLOCK) != 0)
279 : {
280 11760 : auto it(std::find(section_operators.begin(), section_operators.end(), "block"));
281 11760 : CATCH_REQUIRE(it != section_operators.end());
282 11760 : section_operators.erase(it);
283 : }
284 21840 : if((so & advgetopt::SECTION_OPERATOR_INI_FILE) != 0)
285 : {
286 10080 : auto it(std::find(section_operators.begin(), section_operators.end(), "ini-file"));
287 10080 : CATCH_REQUIRE(it != section_operators.end());
288 10080 : section_operators.erase(it);
289 : }
290 :
291 21840 : CATCH_REQUIRE(section_operators.empty());
292 : }
293 : else
294 : {
295 0 : CATCH_REQUIRE(("unknown var_name = " + var_name) == std::string());
296 : }
297 : }
298 :
299 25200 : if(def_lc)
300 : {
301 4200 : CATCH_REQUIRE(static_cast<advgetopt::line_continuation_t>(lc) == advgetopt::line_continuation_t::line_continuation_unix);
302 : }
303 25200 : if(def_ao)
304 : {
305 6300 : CATCH_REQUIRE(real_ao == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
306 : }
307 25200 : if(def_c)
308 : {
309 0 : CATCH_REQUIRE(c == (advgetopt::COMMENT_INI | advgetopt::COMMENT_SHELL));
310 : }
311 : }
312 : }
313 : }
314 : }
315 : }
316 : }
317 : CATCH_END_SECTION()
318 :
319 4 : CATCH_START_SECTION("Check <empty> URL")
320 : advgetopt::conf_file_setup setup(
321 : "/etc/advgetopt/unknown-file.conf"
322 : , advgetopt::line_continuation_t::line_continuation_fortran
323 : , advgetopt::ASSIGNMENT_OPERATOR_COLON
324 : , advgetopt::COMMENT_INI
325 2 : , advgetopt::SECTION_OPERATOR_CPP);
326 :
327 1 : CATCH_REQUIRE_FALSE(setup.is_valid());
328 1 : CATCH_REQUIRE(setup.get_filename() == std::string());
329 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_fortran);
330 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_COLON);
331 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_INI);
332 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_CPP);
333 :
334 1 : CATCH_REQUIRE(setup.get_config_url() == "file:///<empty>?line-continuation=fortran&assignment-operator=colon&comment=ini§ion-operator=cpp");
335 : CATCH_END_SECTION()
336 2 : }
337 :
338 :
339 :
340 3 : CATCH_TEST_CASE("config_reload_tests")
341 : {
342 2 : CATCH_START_SECTION("Load a file, update it, verify it does not get reloaded")
343 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("reload", "load-twice");
344 :
345 : {
346 2 : std::ofstream config_file;
347 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
348 1 : CATCH_REQUIRE(config_file.good());
349 : config_file <<
350 : "# Auto-generated\n"
351 : "param=value\n"
352 : "changing=without reloading is useless\n"
353 : "test=1009\n"
354 1 : ;
355 : }
356 :
357 2 : advgetopt::conf_file::pointer_t file1;
358 : {
359 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
360 : , advgetopt::line_continuation_t::line_continuation_single_line
361 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
362 : , advgetopt::COMMENT_SHELL
363 2 : , advgetopt::SECTION_OPERATOR_NONE);
364 :
365 1 : CATCH_REQUIRE(setup.is_valid());
366 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
367 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
368 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
369 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
370 :
371 1 : file1 = advgetopt::conf_file::get_conf_file(setup);
372 :
373 1 : CATCH_REQUIRE(file1->get_setup().get_config_url() == setup.get_config_url());
374 1 : CATCH_REQUIRE(file1->get_errno() == 0);
375 1 : CATCH_REQUIRE(file1->get_sections().empty());
376 1 : CATCH_REQUIRE(file1->get_parameters().size() == 3);
377 :
378 1 : CATCH_REQUIRE(file1->has_parameter("param"));
379 1 : CATCH_REQUIRE(file1->has_parameter("changing"));
380 1 : CATCH_REQUIRE(file1->has_parameter("test"));
381 :
382 1 : CATCH_REQUIRE(file1->get_parameter("param") == "value");
383 1 : CATCH_REQUIRE(file1->get_parameter("changing") == "without reloading is useless");
384 1 : CATCH_REQUIRE(file1->get_parameter("test") == "1009");
385 : }
386 :
387 : // change all the values now
388 : {
389 2 : std::ofstream config_file;
390 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
391 1 : CATCH_REQUIRE(config_file.good());
392 : config_file <<
393 : "# Auto-generated\n"
394 : "param=new data\n"
395 : "new=this is not even acknowledge\n"
396 : "changing=special value\n"
397 : "test=9010\n"
398 : "level=three\n"
399 1 : ;
400 : }
401 :
402 : // "reloading" that very same file has the old data
403 : {
404 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
405 : , advgetopt::line_continuation_t::line_continuation_single_line
406 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
407 : , advgetopt::COMMENT_SHELL
408 2 : , advgetopt::SECTION_OPERATOR_NONE);
409 :
410 1 : CATCH_REQUIRE(setup.is_valid());
411 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
412 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
413 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
414 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
415 :
416 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
417 :
418 : // exact same pointer
419 : //
420 1 : CATCH_REQUIRE(file == file1);
421 :
422 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
423 1 : CATCH_REQUIRE(file->get_errno() == 0);
424 1 : CATCH_REQUIRE(file->get_sections().empty());
425 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
426 :
427 1 : CATCH_REQUIRE(file->has_parameter("param"));
428 1 : CATCH_REQUIRE(file->has_parameter("changing"));
429 1 : CATCH_REQUIRE(file->has_parameter("test"));
430 :
431 1 : CATCH_REQUIRE(file->get_parameter("param") == "value");
432 1 : CATCH_REQUIRE(file->get_parameter("changing") == "without reloading is useless");
433 1 : CATCH_REQUIRE(file->get_parameter("test") == "1009");
434 : }
435 : CATCH_END_SECTION()
436 1 : }
437 :
438 :
439 :
440 3 : CATCH_TEST_CASE("config_duplicated_variables")
441 : {
442 2 : CATCH_START_SECTION("file with the same variable defined multiple times")
443 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("duplicated-variable", "multiple");
444 :
445 : {
446 2 : std::ofstream config_file;
447 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
448 1 : CATCH_REQUIRE(config_file.good());
449 : config_file <<
450 : "# Auto-generated\n"
451 : "unique = perfect \n"
452 : "multiple = defintions\n"
453 : "another = just fine \t\n"
454 : "multiple = value\r\n"
455 : "good = variable \n"
456 : "multiple = set\n"
457 : "more = data\t \n"
458 1 : ;
459 : }
460 :
461 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
462 : , advgetopt::line_continuation_t::line_continuation_single_line
463 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
464 : , advgetopt::COMMENT_SHELL
465 2 : , advgetopt::SECTION_OPERATOR_NONE);
466 :
467 1 : CATCH_REQUIRE(setup.is_valid());
468 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
469 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
470 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
471 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
472 :
473 : SNAP_CATCH2_NAMESPACE::push_expected_log(
474 : "warning: parameter \"multiple\" on line 5 in"
475 : " configuration file \""
476 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
477 1 : + "\" was found twice in the same configuration file.");
478 : SNAP_CATCH2_NAMESPACE::push_expected_log(
479 : "warning: parameter \"multiple\" on line 7 in"
480 : " configuration file \""
481 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
482 1 : + "\" was found twice in the same configuration file.");
483 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
484 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
485 :
486 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
487 1 : CATCH_REQUIRE(file->get_errno() == 0);
488 1 : CATCH_REQUIRE(file->get_sections().empty());
489 1 : CATCH_REQUIRE(file->get_parameters().size() == 5);
490 :
491 1 : CATCH_REQUIRE(file->has_parameter("unique"));
492 1 : CATCH_REQUIRE(file->has_parameter("another"));
493 1 : CATCH_REQUIRE(file->has_parameter("good"));
494 1 : CATCH_REQUIRE(file->has_parameter("more"));
495 1 : CATCH_REQUIRE(file->has_parameter("multiple"));
496 :
497 1 : CATCH_REQUIRE(file->get_parameter("unique") == "perfect");
498 1 : CATCH_REQUIRE(file->get_parameter("another") == "just fine");
499 1 : CATCH_REQUIRE(file->get_parameter("good") == "variable");
500 1 : CATCH_REQUIRE(file->get_parameter("more") == "data");
501 1 : CATCH_REQUIRE(file->get_parameter("multiple") == "set");
502 :
503 : // we get a warning while reading; but not when directly
504 : // accessing the file object
505 : //
506 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "multiple", "new value"));
507 1 : CATCH_REQUIRE(file->get_parameter("multiple") == "new value");
508 : CATCH_END_SECTION()
509 1 : }
510 :
511 :
512 :
513 3 : CATCH_TEST_CASE("config_callback_calls")
514 : {
515 2 : CATCH_START_SECTION("setup a callback and test the set_parameter()/erase() functions")
516 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("callback-variable", "callback");
517 :
518 : {
519 2 : std::ofstream config_file;
520 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
521 1 : CATCH_REQUIRE(config_file.good());
522 : config_file <<
523 : "# Auto-generated\n"
524 : "unique = perfect \n"
525 : "definition = long value here\n"
526 : "another = just fine \t\n"
527 : "multiple = value\r\n"
528 : "good = variable \n"
529 : "organized = set\n"
530 : "more = data\t \n"
531 1 : ;
532 : }
533 :
534 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
535 : , advgetopt::line_continuation_t::line_continuation_single_line
536 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
537 : , advgetopt::COMMENT_SHELL
538 2 : , advgetopt::SECTION_OPERATOR_NONE);
539 :
540 1 : CATCH_REQUIRE(setup.is_valid());
541 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
542 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
543 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
544 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
545 :
546 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
547 :
548 2 : struct conf_data
549 : {
550 : advgetopt::conf_file::pointer_t f_conf_file = advgetopt::conf_file::pointer_t();
551 : advgetopt::callback_action_t f_expected_action = advgetopt::callback_action_t::created;
552 : std::string f_expected_variable = std::string();
553 : std::string f_expected_value = std::string();
554 : };
555 2 : conf_data cf_data;
556 1 : cf_data.f_conf_file = file;
557 :
558 : struct conf_callback
559 : {
560 5 : void operator () (advgetopt::conf_file::pointer_t conf_file
561 : , advgetopt::callback_action_t action
562 : , std::string const & variable_name
563 : , std::string const & value)
564 : {
565 5 : CATCH_REQUIRE(conf_file == f_data->f_conf_file);
566 5 : CATCH_REQUIRE(action == f_data->f_expected_action);
567 5 : CATCH_REQUIRE(variable_name == f_data->f_expected_variable);
568 5 : CATCH_REQUIRE(value == f_data->f_expected_value);
569 5 : CATCH_REQUIRE(conf_file->get_parameter(variable_name) == f_data->f_expected_value);
570 5 : }
571 :
572 : conf_data * f_data = nullptr;
573 : };
574 1 : conf_callback cf;
575 1 : cf.f_data = &cf_data;
576 :
577 1 : file->set_callback(cf);
578 :
579 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
580 1 : CATCH_REQUIRE(file->get_errno() == 0);
581 1 : CATCH_REQUIRE_FALSE(file->was_modified());
582 1 : CATCH_REQUIRE(file->get_sections().empty());
583 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
584 :
585 1 : CATCH_REQUIRE(file->has_parameter("unique"));
586 1 : CATCH_REQUIRE(file->has_parameter("definition"));
587 1 : CATCH_REQUIRE(file->has_parameter("another"));
588 1 : CATCH_REQUIRE(file->has_parameter("multiple"));
589 1 : CATCH_REQUIRE(file->has_parameter("good"));
590 1 : CATCH_REQUIRE(file->has_parameter("organized"));
591 1 : CATCH_REQUIRE(file->has_parameter("more"));
592 :
593 1 : CATCH_REQUIRE(file->get_parameter("unique") == "perfect");
594 1 : CATCH_REQUIRE(file->get_parameter("definition") == "long value here");
595 1 : CATCH_REQUIRE(file->get_parameter("another") == "just fine");
596 1 : CATCH_REQUIRE(file->get_parameter("multiple") == "value");
597 1 : CATCH_REQUIRE(file->get_parameter("good") == "variable");
598 1 : CATCH_REQUIRE(file->get_parameter("organized") == "set");
599 1 : CATCH_REQUIRE(file->get_parameter("more") == "data");
600 :
601 : // updated action
602 : //
603 1 : cf_data.f_expected_action = advgetopt::callback_action_t::updated;
604 1 : cf_data.f_expected_variable = "multiple";
605 1 : cf_data.f_expected_value = "new value";
606 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "multiple", "new value"));
607 1 : CATCH_REQUIRE(file->was_modified());
608 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
609 1 : CATCH_REQUIRE(file->get_parameter("multiple") == "new value");
610 :
611 : // created action
612 : //
613 1 : cf_data.f_expected_action = advgetopt::callback_action_t::created;
614 1 : cf_data.f_expected_variable = "new-param";
615 1 : cf_data.f_expected_value = "with this value";
616 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "new_param", "with this value"));
617 1 : CATCH_REQUIRE(file->was_modified());
618 1 : CATCH_REQUIRE(file->get_parameters().size() == 8);
619 1 : CATCH_REQUIRE(file->has_parameter("new-param"));
620 1 : CATCH_REQUIRE(file->get_parameter("new-param") == "with this value");
621 1 : CATCH_REQUIRE(file->has_parameter("new_param"));
622 1 : CATCH_REQUIRE(file->get_parameter("new_param") == "with this value");
623 :
624 : // updated action when modifying
625 : //
626 1 : cf_data.f_expected_action = advgetopt::callback_action_t::updated;
627 1 : cf_data.f_expected_variable = "new-param";
628 1 : cf_data.f_expected_value = "change completely";
629 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "new_param", "change completely"));
630 1 : CATCH_REQUIRE(file->was_modified());
631 1 : CATCH_REQUIRE(file->get_parameters().size() == 8);
632 1 : CATCH_REQUIRE(file->has_parameter("new-param"));
633 1 : CATCH_REQUIRE(file->get_parameter("new-param") == "change completely");
634 1 : CATCH_REQUIRE(file->has_parameter("new_param"));
635 1 : CATCH_REQUIRE(file->get_parameter("new_param") == "change completely");
636 :
637 : // erased action
638 : //
639 1 : cf_data.f_expected_action = advgetopt::callback_action_t::erased;
640 1 : cf_data.f_expected_variable = "new-param";
641 1 : cf_data.f_expected_value = std::string();
642 1 : CATCH_REQUIRE(file->erase_parameter("new_param"));
643 1 : CATCH_REQUIRE(file->was_modified());
644 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
645 1 : CATCH_REQUIRE_FALSE(file->has_parameter("new-param"));
646 1 : CATCH_REQUIRE(file->get_parameter("new-param") == std::string());
647 1 : CATCH_REQUIRE_FALSE(file->has_parameter("new_param"));
648 1 : CATCH_REQUIRE(file->get_parameter("new_param") == std::string());
649 1 : CATCH_REQUIRE_FALSE(file->erase_parameter("new_param"));
650 :
651 : // created action again (because it was erased)
652 : //
653 1 : cf_data.f_expected_action = advgetopt::callback_action_t::created;
654 1 : cf_data.f_expected_variable = "new-param";
655 1 : cf_data.f_expected_value = "with this value";
656 1 : CATCH_REQUIRE(file->set_parameter(std::string(), "new_param", "with this value"));
657 1 : CATCH_REQUIRE(file->was_modified());
658 1 : CATCH_REQUIRE(file->get_parameters().size() == 8);
659 1 : CATCH_REQUIRE(file->has_parameter("new-param"));
660 1 : CATCH_REQUIRE(file->get_parameter("new-param") == "with this value");
661 1 : CATCH_REQUIRE(file->has_parameter("new_param"));
662 1 : CATCH_REQUIRE(file->get_parameter("new_param") == "with this value");
663 :
664 : // until you save it remains true even if you were to restore the
665 : // state to "normal" (we do not keep a copy of the original value
666 : // as found in the file.)
667 : //
668 1 : CATCH_REQUIRE(file->was_modified());
669 : CATCH_END_SECTION()
670 1 : }
671 :
672 :
673 :
674 8 : CATCH_TEST_CASE("config_line_continuation_tests")
675 : {
676 12 : CATCH_START_SECTION("single_line")
677 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "single-line");
678 :
679 : {
680 2 : std::ofstream config_file;
681 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
682 1 : CATCH_REQUIRE(config_file.good());
683 : config_file <<
684 : "# Auto-generated\n"
685 : "normal=param\n"
686 : "\n"
687 : "rfc-822=start here\n"
688 : " continue=there\n"
689 : "\n"
690 : "msdos=end with &\n"
691 : " and-continue=on next line\n"
692 : "\n"
693 : "unix=end with \\\n"
694 : "to-continue=like this\n"
695 : "\n"
696 : "fortran=fortran is funny\n"
697 : "&since=it starts with an & on the following line\n"
698 : "\n"
699 : "semicolon=this ends with\n"
700 : "a=semi-colon only;\n"
701 1 : ;
702 : }
703 :
704 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
705 : , advgetopt::line_continuation_t::line_continuation_single_line
706 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
707 : , advgetopt::COMMENT_SHELL
708 2 : , advgetopt::SECTION_OPERATOR_NONE);
709 :
710 1 : CATCH_REQUIRE(setup.is_valid());
711 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
712 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
713 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
714 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
715 :
716 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
717 :
718 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
719 1 : CATCH_REQUIRE(file->get_errno() == 0);
720 1 : CATCH_REQUIRE(file->get_sections().empty());
721 1 : CATCH_REQUIRE(file->get_parameters().size() == 11);
722 :
723 1 : CATCH_REQUIRE(file->has_parameter("normal"));
724 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
725 1 : CATCH_REQUIRE(file->has_parameter("continue"));
726 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
727 1 : CATCH_REQUIRE(file->has_parameter("and-continue"));
728 1 : CATCH_REQUIRE(file->has_parameter("unix"));
729 1 : CATCH_REQUIRE(file->has_parameter("to-continue"));
730 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
731 1 : CATCH_REQUIRE(file->has_parameter("&since"));
732 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
733 1 : CATCH_REQUIRE(file->has_parameter("a"));
734 :
735 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
736 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start here");
737 1 : CATCH_REQUIRE(file->get_parameter("continue") == "there");
738 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with &");
739 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == "on next line");
740 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with \\");
741 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == "like this");
742 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funny");
743 1 : CATCH_REQUIRE(file->get_parameter("&since") == "it starts with an & on the following line");
744 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
745 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
746 :
747 1114113 : for(int c(0); c < 0x110000; ++c)
748 : {
749 1114112 : if(c == '=')
750 : {
751 1 : CATCH_REQUIRE(file->is_assignment_operator(c));
752 : }
753 : else
754 : {
755 1114111 : CATCH_REQUIRE_FALSE(file->is_assignment_operator(c));
756 : }
757 : }
758 : CATCH_END_SECTION()
759 :
760 12 : CATCH_START_SECTION("rfc822")
761 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "rfc822");
762 :
763 : {
764 2 : std::ofstream config_file;
765 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
766 1 : CATCH_REQUIRE(config_file.good());
767 : config_file <<
768 : "# Auto-generated\n"
769 : "normal=param\n"
770 : "\n"
771 : "rfc-822=start here\n"
772 : " continue=there\n"
773 : "\n"
774 : "msdos=end with &\n"
775 : " and-continue=on next line\n"
776 : "\n"
777 : "unix=end with \\\n"
778 : "to-continue=like this\n"
779 : "\n"
780 : "fortran=fortran is funny\n"
781 : "&since=it starts with an & on the following line\n"
782 : "\n"
783 : "semicolon=this ends with\n"
784 : "a=semi-colon only;\n"
785 1 : ;
786 : }
787 :
788 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
789 : , advgetopt::line_continuation_t::line_continuation_rfc_822
790 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
791 : , advgetopt::COMMENT_SHELL
792 2 : , advgetopt::SECTION_OPERATOR_NONE);
793 :
794 1 : CATCH_REQUIRE(setup.is_valid());
795 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_rfc_822);
796 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
797 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
798 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
799 :
800 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
801 :
802 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
803 1 : CATCH_REQUIRE(file->get_errno() == 0);
804 1 : CATCH_REQUIRE(file->get_sections().empty());
805 1 : CATCH_REQUIRE(file->get_parameters().size() == 9);
806 :
807 1 : CATCH_REQUIRE(file->has_parameter("normal"));
808 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
809 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
810 1 : CATCH_REQUIRE_FALSE(file->has_parameter("and-continue"));
811 1 : CATCH_REQUIRE(file->has_parameter("unix"));
812 1 : CATCH_REQUIRE(file->has_parameter("to-continue"));
813 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
814 1 : CATCH_REQUIRE(file->has_parameter("&since"));
815 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
816 1 : CATCH_REQUIRE(file->has_parameter("a"));
817 :
818 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
819 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start herecontinue=there");
820 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with &and-continue=on next line");
821 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == std::string());
822 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with \\");
823 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == "like this");
824 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funny");
825 1 : CATCH_REQUIRE(file->get_parameter("&since") == "it starts with an & on the following line");
826 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
827 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
828 : CATCH_END_SECTION()
829 :
830 12 : CATCH_START_SECTION("msdos")
831 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "msdos");
832 :
833 : {
834 2 : std::ofstream config_file;
835 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
836 1 : CATCH_REQUIRE(config_file.good());
837 : config_file <<
838 : "# Auto-generated\n"
839 : "normal=param\n"
840 : "\n"
841 : "rfc-822=start here\n"
842 : " continue=there\n"
843 : "\n"
844 : "msdos=end with &\n"
845 : " and-continue=on next line\n"
846 : "\n"
847 : "unix=end with \\\n"
848 : "to-continue=like this\n"
849 : "\n"
850 : "fortran=fortran is funny\n"
851 : "&since=it starts with an & on the following line\n"
852 : "\n"
853 : "semicolon=this ends with\n"
854 : "a=semi-colon only;\n"
855 1 : ;
856 : }
857 :
858 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
859 : , advgetopt::line_continuation_t::line_continuation_msdos
860 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
861 : , advgetopt::COMMENT_SHELL
862 2 : , advgetopt::SECTION_OPERATOR_NONE);
863 :
864 1 : CATCH_REQUIRE(setup.is_valid());
865 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_msdos);
866 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
867 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
868 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
869 :
870 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
871 :
872 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
873 1 : CATCH_REQUIRE(file->get_errno() == 0);
874 1 : CATCH_REQUIRE(file->get_sections().empty());
875 1 : CATCH_REQUIRE(file->get_parameters().size() == 10);
876 :
877 1 : CATCH_REQUIRE(file->has_parameter("normal"));
878 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
879 1 : CATCH_REQUIRE(file->has_parameter("continue"));
880 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
881 1 : CATCH_REQUIRE_FALSE(file->has_parameter("and-continue"));
882 1 : CATCH_REQUIRE(file->has_parameter("unix"));
883 1 : CATCH_REQUIRE(file->has_parameter("to-continue"));
884 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
885 1 : CATCH_REQUIRE(file->has_parameter("&since"));
886 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
887 1 : CATCH_REQUIRE(file->has_parameter("a"));
888 :
889 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
890 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start here");
891 1 : CATCH_REQUIRE(file->get_parameter("continue") == "there");
892 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with and-continue=on next line");
893 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == std::string());
894 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with \\");
895 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == "like this");
896 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funny");
897 1 : CATCH_REQUIRE(file->get_parameter("&since") == "it starts with an & on the following line");
898 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
899 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
900 : CATCH_END_SECTION()
901 :
902 12 : CATCH_START_SECTION("unix")
903 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "unix");
904 :
905 : {
906 2 : std::ofstream config_file;
907 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
908 1 : CATCH_REQUIRE(config_file.good());
909 : config_file <<
910 : "# Auto-generated\n"
911 : "normal=param\n"
912 : "\n"
913 : "rfc-822=start here\n"
914 : " continue=there\n"
915 : "\n"
916 : "msdos=end with &\n"
917 : " and-continue=on next line\n"
918 : "\n"
919 : "unix=end with \\\n"
920 : "to-continue=like this\n"
921 : "\n"
922 : "fortran=fortran is funny\n"
923 : "&since=it starts with an & on the following line\n"
924 : "\n"
925 : "semicolon=this ends with\n"
926 : "a=semi-colon only;\n"
927 1 : ;
928 : }
929 :
930 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
931 : , advgetopt::line_continuation_t::line_continuation_unix
932 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
933 : , advgetopt::COMMENT_SHELL
934 2 : , advgetopt::SECTION_OPERATOR_NONE);
935 :
936 1 : CATCH_REQUIRE(setup.is_valid());
937 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
938 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
939 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
940 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
941 :
942 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
943 :
944 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
945 1 : CATCH_REQUIRE(file->get_errno() == 0);
946 1 : CATCH_REQUIRE(file->get_sections().empty());
947 1 : CATCH_REQUIRE(file->get_parameters().size() == 10);
948 :
949 1 : CATCH_REQUIRE(file->has_parameter("normal"));
950 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
951 1 : CATCH_REQUIRE(file->has_parameter("continue"));
952 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
953 1 : CATCH_REQUIRE(file->has_parameter("and-continue"));
954 1 : CATCH_REQUIRE(file->has_parameter("unix"));
955 1 : CATCH_REQUIRE_FALSE(file->has_parameter("to-continue"));
956 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
957 1 : CATCH_REQUIRE(file->has_parameter("&since"));
958 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
959 1 : CATCH_REQUIRE(file->has_parameter("a"));
960 :
961 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
962 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start here");
963 1 : CATCH_REQUIRE(file->get_parameter("continue") == "there");
964 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with &");
965 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == "on next line");
966 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with to-continue=like this");
967 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == std::string());
968 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funny");
969 1 : CATCH_REQUIRE(file->get_parameter("&since") == "it starts with an & on the following line");
970 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
971 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
972 : CATCH_END_SECTION()
973 :
974 12 : CATCH_START_SECTION("fortran")
975 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "fortran");
976 :
977 : {
978 2 : std::ofstream config_file;
979 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
980 1 : CATCH_REQUIRE(config_file.good());
981 : config_file <<
982 : "# Auto-generated\n"
983 : "normal=param\n"
984 : "\n"
985 : "rfc-822=start here\n"
986 : " continue=there\n"
987 : "\n"
988 : "msdos=end with &\n"
989 : " and-continue=on next line\n"
990 : "\n"
991 : "unix=end with \\\n"
992 : "to-continue=like this\n"
993 : "\n"
994 : "fortran=fortran is funny\n"
995 : "&since=it starts with an & on the following line\n"
996 : "\n"
997 : "semicolon=this ends with\n"
998 : "a=semi-colon only;\n"
999 1 : ;
1000 : }
1001 :
1002 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1003 : , advgetopt::line_continuation_t::line_continuation_fortran
1004 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1005 : , advgetopt::COMMENT_SHELL
1006 2 : , advgetopt::SECTION_OPERATOR_NONE);
1007 :
1008 1 : CATCH_REQUIRE(setup.is_valid());
1009 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_fortran);
1010 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1011 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1012 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1013 :
1014 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1015 :
1016 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1017 1 : CATCH_REQUIRE(file->get_errno() == 0);
1018 1 : CATCH_REQUIRE(file->get_sections().empty());
1019 1 : CATCH_REQUIRE(file->get_parameters().size() == 10);
1020 :
1021 1 : CATCH_REQUIRE(file->has_parameter("normal"));
1022 1 : CATCH_REQUIRE(file->has_parameter("rfc-822"));
1023 1 : CATCH_REQUIRE(file->has_parameter("continue"));
1024 1 : CATCH_REQUIRE(file->has_parameter("msdos"));
1025 1 : CATCH_REQUIRE(file->has_parameter("and-continue"));
1026 1 : CATCH_REQUIRE(file->has_parameter("unix"));
1027 1 : CATCH_REQUIRE(file->has_parameter("to-continue"));
1028 1 : CATCH_REQUIRE(file->has_parameter("fortran"));
1029 1 : CATCH_REQUIRE_FALSE(file->has_parameter("&since"));
1030 1 : CATCH_REQUIRE(file->has_parameter("semicolon"));
1031 1 : CATCH_REQUIRE(file->has_parameter("a"));
1032 :
1033 1 : CATCH_REQUIRE(file->get_parameter("normal") == "param");
1034 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == "start here");
1035 1 : CATCH_REQUIRE(file->get_parameter("continue") == "there");
1036 1 : CATCH_REQUIRE(file->get_parameter("msdos") == "end with &");
1037 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == "on next line");
1038 1 : CATCH_REQUIRE(file->get_parameter("unix") == "end with \\");
1039 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == "like this");
1040 1 : CATCH_REQUIRE(file->get_parameter("fortran") == "fortran is funnysince=it starts with an & on the following line");
1041 1 : CATCH_REQUIRE(file->get_parameter("&since") == std::string());
1042 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == "this ends with");
1043 1 : CATCH_REQUIRE(file->get_parameter("a") == "semi-colon only;");
1044 : CATCH_END_SECTION()
1045 :
1046 12 : CATCH_START_SECTION("semicolon")
1047 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("line-continuation", "semicolon");
1048 :
1049 : {
1050 2 : std::ofstream config_file;
1051 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1052 1 : CATCH_REQUIRE(config_file.good());
1053 : config_file <<
1054 : "# Auto-generated\r\n"
1055 : "normal=param\r\n"
1056 : "\r\n"
1057 : "rfc-822=start here\r\n"
1058 : " continue=there\r\n"
1059 : "\r\n"
1060 : "msdos=end with &\r"
1061 : " and-continue=on next line\r\n"
1062 : "\r\n"
1063 : "unix=end with \\\r\n"
1064 : "to-continue=like this\r"
1065 : "\r\n"
1066 : "fortran=fortran is funny\r\n"
1067 : "&since=it starts with an & on the following line\r\n"
1068 : "\r"
1069 : "semicolon=this ends with\r\n"
1070 : "a=semi-colon only;\r\n"
1071 1 : ;
1072 : }
1073 :
1074 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1075 : , advgetopt::line_continuation_t::line_continuation_semicolon
1076 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1077 : , advgetopt::COMMENT_SHELL
1078 2 : , advgetopt::SECTION_OPERATOR_NONE);
1079 :
1080 1 : CATCH_REQUIRE(setup.is_valid());
1081 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_semicolon);
1082 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1083 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1084 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1085 :
1086 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1087 :
1088 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1089 1 : CATCH_REQUIRE(file->get_errno() == 0);
1090 1 : CATCH_REQUIRE(file->get_sections().empty());
1091 1 : CATCH_REQUIRE(file->get_parameters().size() == 1);
1092 :
1093 1 : CATCH_REQUIRE(file->has_parameter("normal"));
1094 1 : CATCH_REQUIRE_FALSE(file->has_parameter("rfc-822"));
1095 1 : CATCH_REQUIRE_FALSE(file->has_parameter("continue"));
1096 1 : CATCH_REQUIRE_FALSE(file->has_parameter("msdos"));
1097 1 : CATCH_REQUIRE_FALSE(file->has_parameter("and-continue"));
1098 1 : CATCH_REQUIRE_FALSE(file->has_parameter("unix"));
1099 1 : CATCH_REQUIRE_FALSE(file->has_parameter("to-continue"));
1100 1 : CATCH_REQUIRE_FALSE(file->has_parameter("fortran"));
1101 1 : CATCH_REQUIRE_FALSE(file->has_parameter("&since"));
1102 1 : CATCH_REQUIRE_FALSE(file->has_parameter("semicolon"));
1103 1 : CATCH_REQUIRE_FALSE(file->has_parameter("a"));
1104 :
1105 1 : CATCH_REQUIRE(file->get_parameter("normal") == std::string("param\n"
1106 : "\n"
1107 : "rfc-822=start here\n"
1108 : " continue=there\n"
1109 : "\n"
1110 : "msdos=end with &\n"
1111 : " and-continue=on next line\n"
1112 : "\n"
1113 : "unix=end with \\\n"
1114 : "to-continue=like this\n"
1115 : "\n"
1116 : "fortran=fortran is funny\n"
1117 : "&since=it starts with an & on the following line\n"
1118 : "\n"
1119 : "semicolon=this ends with\n"
1120 : "a=semi-colon only"));
1121 1 : CATCH_REQUIRE(file->get_parameter("rfc-822") == std::string());
1122 1 : CATCH_REQUIRE(file->get_parameter("continue") == std::string());
1123 1 : CATCH_REQUIRE(file->get_parameter("msdos") == std::string());
1124 1 : CATCH_REQUIRE(file->get_parameter("and-continue") == std::string());
1125 1 : CATCH_REQUIRE(file->get_parameter("unix") == std::string());
1126 1 : CATCH_REQUIRE(file->get_parameter("to-continue") == std::string());
1127 1 : CATCH_REQUIRE(file->get_parameter("fortran") == std::string());
1128 1 : CATCH_REQUIRE(file->get_parameter("&since") == std::string());
1129 1 : CATCH_REQUIRE(file->get_parameter("semicolon") == std::string());
1130 1 : CATCH_REQUIRE(file->get_parameter("a") == std::string());
1131 : CATCH_END_SECTION()
1132 6 : }
1133 :
1134 :
1135 :
1136 6 : CATCH_TEST_CASE("config_assignment_operator_tests")
1137 : {
1138 8 : CATCH_START_SECTION("equal")
1139 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("assignment-operator", "equal");
1140 :
1141 : {
1142 2 : std::ofstream config_file;
1143 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1144 1 : CATCH_REQUIRE(config_file.good());
1145 : config_file <<
1146 : "# Auto-generated\n"
1147 : "equal=value\n"
1148 : "\n"
1149 : "name_value=127\n"
1150 : "\n"
1151 : "and=no operator\n"
1152 1 : ;
1153 : }
1154 :
1155 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1156 : , advgetopt::line_continuation_t::line_continuation_single_line
1157 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1158 : , advgetopt::COMMENT_SHELL
1159 2 : , advgetopt::SECTION_OPERATOR_NONE);
1160 :
1161 1 : CATCH_REQUIRE(setup.is_valid());
1162 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1163 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1164 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1165 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1166 :
1167 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1168 :
1169 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1170 1 : CATCH_REQUIRE(file->get_errno() == 0);
1171 1 : CATCH_REQUIRE(file->get_sections().empty());
1172 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1173 :
1174 1 : CATCH_REQUIRE(file->has_parameter("equal"));
1175 1 : CATCH_REQUIRE(file->has_parameter("name-value"));
1176 1 : CATCH_REQUIRE(file->has_parameter("and"));
1177 :
1178 1 : CATCH_REQUIRE(file->get_parameter("equal") == "value");
1179 1 : CATCH_REQUIRE(file->get_parameter("name-value") == "127");
1180 1 : CATCH_REQUIRE(file->get_parameter("and") == "no operator");
1181 : CATCH_END_SECTION()
1182 :
1183 8 : CATCH_START_SECTION("colon")
1184 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("assignment-operator", "colon");
1185 :
1186 : {
1187 2 : std::ofstream config_file;
1188 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1189 1 : CATCH_REQUIRE(config_file.good());
1190 : config_file <<
1191 : "# Auto-generated\n"
1192 : "equal_value\n"
1193 : "\n"
1194 : "name:value=127\n"
1195 : "\n"
1196 : "and_no-operator\n"
1197 1 : ;
1198 : }
1199 :
1200 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1201 : , advgetopt::line_continuation_t::line_continuation_single_line
1202 : , advgetopt::ASSIGNMENT_OPERATOR_COLON
1203 : , advgetopt::COMMENT_SHELL
1204 2 : , advgetopt::SECTION_OPERATOR_NONE);
1205 :
1206 1 : CATCH_REQUIRE(setup.is_valid());
1207 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1208 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_COLON);
1209 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1210 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1211 :
1212 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1213 :
1214 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1215 1 : CATCH_REQUIRE(file->get_errno() == 0);
1216 1 : CATCH_REQUIRE(file->get_sections().empty());
1217 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1218 :
1219 1 : CATCH_REQUIRE(file->has_parameter("equal-value"));
1220 1 : CATCH_REQUIRE(file->has_parameter("name"));
1221 1 : CATCH_REQUIRE(file->has_parameter("and-no-operator"));
1222 :
1223 1 : CATCH_REQUIRE(file->get_parameter("equal-value") == std::string());
1224 1 : CATCH_REQUIRE(file->get_parameter("name") == "value=127");
1225 1 : CATCH_REQUIRE(file->get_parameter("and-no-operator") == std::string());
1226 : CATCH_END_SECTION()
1227 :
1228 8 : CATCH_START_SECTION("space")
1229 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("assignment-operator", "space");
1230 :
1231 : {
1232 2 : std::ofstream config_file;
1233 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1234 1 : CATCH_REQUIRE(config_file.good());
1235 : config_file <<
1236 : "# Auto-generated\n"
1237 : "equal-value\n"
1238 : "\n"
1239 : "name 127\n"
1240 : "\n"
1241 : "and-no operator\n"
1242 1 : ;
1243 : }
1244 :
1245 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1246 : , advgetopt::line_continuation_t::line_continuation_single_line
1247 : , advgetopt::ASSIGNMENT_OPERATOR_SPACE
1248 : , advgetopt::COMMENT_SHELL
1249 2 : , advgetopt::SECTION_OPERATOR_NONE);
1250 :
1251 1 : CATCH_REQUIRE(setup.is_valid());
1252 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1253 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_SPACE);
1254 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1255 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1256 :
1257 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1258 :
1259 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1260 1 : CATCH_REQUIRE(file->get_errno() == 0);
1261 1 : CATCH_REQUIRE(file->get_sections().empty());
1262 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1263 :
1264 1 : CATCH_REQUIRE(file->has_parameter("equal-value"));
1265 1 : CATCH_REQUIRE(file->has_parameter("name"));
1266 1 : CATCH_REQUIRE(file->has_parameter("and-no"));
1267 :
1268 1 : CATCH_REQUIRE(file->get_parameter("equal-value") == std::string());
1269 1 : CATCH_REQUIRE(file->get_parameter("name") == "127");
1270 1 : CATCH_REQUIRE(file->get_parameter("and-no") == "operator");
1271 : CATCH_END_SECTION()
1272 :
1273 8 : CATCH_START_SECTION("equal_colon_and_space")
1274 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("assignment-operator", "all");
1275 :
1276 : {
1277 2 : std::ofstream config_file;
1278 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1279 1 : CATCH_REQUIRE(config_file.good());
1280 : config_file <<
1281 : "# Auto-generated\n"
1282 : "equal=value\n"
1283 : "\n"
1284 : "name: 127\n"
1285 : "\n"
1286 : "and no operator\n"
1287 1 : ;
1288 : }
1289 :
1290 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1291 : , advgetopt::line_continuation_t::line_continuation_single_line
1292 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1293 : | advgetopt::ASSIGNMENT_OPERATOR_COLON
1294 : | advgetopt::ASSIGNMENT_OPERATOR_SPACE
1295 : , advgetopt::COMMENT_SHELL
1296 2 : , advgetopt::SECTION_OPERATOR_NONE);
1297 :
1298 1 : CATCH_REQUIRE(setup.is_valid());
1299 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1300 1 : CATCH_REQUIRE(setup.get_assignment_operator() == (advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1301 : | advgetopt::ASSIGNMENT_OPERATOR_COLON
1302 : | advgetopt::ASSIGNMENT_OPERATOR_SPACE));
1303 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1304 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1305 :
1306 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1307 :
1308 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1309 1 : CATCH_REQUIRE(file->get_errno() == 0);
1310 1 : CATCH_REQUIRE(file->get_sections().empty());
1311 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1312 :
1313 1 : CATCH_REQUIRE(file->has_parameter("equal"));
1314 1 : CATCH_REQUIRE(file->has_parameter("name"));
1315 1 : CATCH_REQUIRE(file->has_parameter("and"));
1316 :
1317 1 : CATCH_REQUIRE(file->get_parameter("equal") == "value");
1318 1 : CATCH_REQUIRE(file->get_parameter("name") == "127");
1319 1 : CATCH_REQUIRE(file->get_parameter("and") == "no operator");
1320 : CATCH_END_SECTION()
1321 4 : }
1322 :
1323 :
1324 :
1325 :
1326 :
1327 6 : CATCH_TEST_CASE("config_comment_tests")
1328 : {
1329 8 : CATCH_START_SECTION("ini comment")
1330 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("comment", "ini");
1331 :
1332 : {
1333 2 : std::ofstream config_file;
1334 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1335 1 : CATCH_REQUIRE(config_file.good());
1336 : config_file <<
1337 : "; Auto-generated\n"
1338 : "ini=comment\n"
1339 : ";ignore=this one\n"
1340 : "is=the semi-colon\n"
1341 : ";continuation=with Unix\\\n"
1342 : "also=works for\\\n"
1343 : "comments\n"
1344 1 : ;
1345 : }
1346 :
1347 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1348 : , advgetopt::line_continuation_t::line_continuation_unix
1349 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1350 : , advgetopt::COMMENT_INI
1351 2 : , advgetopt::SECTION_OPERATOR_NONE);
1352 :
1353 1 : CATCH_REQUIRE(setup.is_valid());
1354 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1355 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1356 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_INI);
1357 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1358 :
1359 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1360 :
1361 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1362 1 : CATCH_REQUIRE(file->get_errno() == 0);
1363 1 : CATCH_REQUIRE(file->get_sections().empty());
1364 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
1365 :
1366 1 : CATCH_REQUIRE(file->has_parameter("ini"));
1367 1 : CATCH_REQUIRE(file->has_parameter("is"));
1368 :
1369 1 : CATCH_REQUIRE(file->get_parameter("ini") == "comment");
1370 1 : CATCH_REQUIRE(file->get_parameter("is") == "the semi-colon");
1371 : CATCH_END_SECTION()
1372 :
1373 8 : CATCH_START_SECTION("shell comment")
1374 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("comment", "shell");
1375 :
1376 : {
1377 2 : std::ofstream config_file;
1378 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1379 1 : CATCH_REQUIRE(config_file.good());
1380 : config_file <<
1381 : "# Auto-generated\n"
1382 : "shell=comment\n"
1383 : "#ignore=this one\n"
1384 : "is=the hash (`#`) character\n"
1385 : "#continuation=with Unix\\\n"
1386 : "also=works for\\\n"
1387 : "comments\n"
1388 1 : ;
1389 : }
1390 :
1391 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1392 : , advgetopt::line_continuation_t::line_continuation_unix
1393 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1394 : , advgetopt::COMMENT_SHELL
1395 2 : , advgetopt::SECTION_OPERATOR_NONE);
1396 :
1397 1 : CATCH_REQUIRE(setup.is_valid());
1398 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1399 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1400 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1401 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1402 :
1403 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1404 :
1405 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1406 1 : CATCH_REQUIRE(file->get_errno() == 0);
1407 1 : CATCH_REQUIRE(file->get_sections().empty());
1408 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
1409 :
1410 1 : CATCH_REQUIRE(file->has_parameter("shell"));
1411 1 : CATCH_REQUIRE(file->has_parameter("is"));
1412 :
1413 1 : CATCH_REQUIRE(file->get_parameter("shell") == "comment");
1414 1 : CATCH_REQUIRE(file->get_parameter("is") == "the hash (`#`) character");
1415 : CATCH_END_SECTION()
1416 :
1417 8 : CATCH_START_SECTION("C++ comment")
1418 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("comment", "cpp");
1419 :
1420 : {
1421 2 : std::ofstream config_file;
1422 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1423 1 : CATCH_REQUIRE(config_file.good());
1424 : config_file <<
1425 : "// Auto-generated\n"
1426 : "cpp=comment\n"
1427 : "//ignore=this one\n"
1428 : "is=the double slash (`//`)\n"
1429 : "//continuation=with Unix\\\n"
1430 : "also=works for\\\n"
1431 : "comments\n"
1432 1 : ;
1433 : }
1434 :
1435 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1436 : , advgetopt::line_continuation_t::line_continuation_unix
1437 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1438 : , advgetopt::COMMENT_CPP
1439 2 : , advgetopt::SECTION_OPERATOR_NONE);
1440 :
1441 1 : CATCH_REQUIRE(setup.is_valid());
1442 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1443 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1444 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_CPP);
1445 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1446 :
1447 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1448 :
1449 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1450 1 : CATCH_REQUIRE(file->get_errno() == 0);
1451 1 : CATCH_REQUIRE(file->get_sections().empty());
1452 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
1453 :
1454 1 : CATCH_REQUIRE(file->has_parameter("cpp"));
1455 1 : CATCH_REQUIRE(file->has_parameter("is"));
1456 :
1457 1 : CATCH_REQUIRE(file->get_parameter("cpp") == "comment");
1458 1 : CATCH_REQUIRE(file->get_parameter("is") == "the double slash (`//`)");
1459 : CATCH_END_SECTION()
1460 :
1461 8 : CATCH_START_SECTION("All three comments")
1462 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("comment", "all-comments");
1463 :
1464 : {
1465 2 : std::ofstream config_file;
1466 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1467 1 : CATCH_REQUIRE(config_file.good());
1468 : config_file <<
1469 : "// Auto-generated\n"
1470 : "all=comments\n"
1471 : ";ignore=this one\n"
1472 : "together=for powerful config support\n"
1473 : "#continuation=with Unix\\\n"
1474 : "also=works for\\\n"
1475 : "comments\n"
1476 : "but=maybe\n"
1477 : ";we=should\\\n"
1478 : "test=continuation\n"
1479 : "//with=each\\\n"
1480 : "each=type of comment\n"
1481 1 : ;
1482 : }
1483 :
1484 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1485 : , advgetopt::line_continuation_t::line_continuation_unix
1486 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1487 : , advgetopt::COMMENT_INI | advgetopt::COMMENT_SHELL | advgetopt::COMMENT_CPP
1488 2 : , advgetopt::SECTION_OPERATOR_NONE);
1489 :
1490 1 : CATCH_REQUIRE(setup.is_valid());
1491 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1492 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1493 1 : CATCH_REQUIRE(setup.get_comment() == (advgetopt::COMMENT_INI | advgetopt::COMMENT_SHELL | advgetopt::COMMENT_CPP));
1494 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1495 :
1496 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1497 :
1498 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1499 1 : CATCH_REQUIRE(file->get_errno() == 0);
1500 1 : CATCH_REQUIRE(file->get_sections().empty());
1501 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1502 :
1503 1 : CATCH_REQUIRE(file->has_parameter("all"));
1504 1 : CATCH_REQUIRE(file->has_parameter("together"));
1505 1 : CATCH_REQUIRE(file->has_parameter("but"));
1506 :
1507 1 : CATCH_REQUIRE(file->get_parameter("all") == "comments");
1508 1 : CATCH_REQUIRE(file->get_parameter("together") == "for powerful config support");
1509 1 : CATCH_REQUIRE(file->get_parameter("but") == "maybe");
1510 : CATCH_END_SECTION()
1511 4 : }
1512 :
1513 :
1514 :
1515 :
1516 :
1517 7 : CATCH_TEST_CASE("config_section_tests")
1518 : {
1519 10 : CATCH_START_SECTION("section operator c (.)")
1520 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-c");
1521 :
1522 : {
1523 2 : std::ofstream config_file;
1524 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1525 1 : CATCH_REQUIRE(config_file.good());
1526 : config_file <<
1527 : "# Auto-generated\n"
1528 : "a=color\n"
1529 : "a.b=red\n"
1530 : "a.b.c=122\n"
1531 : "m=size\n"
1532 : "z=edge\n"
1533 : "z.b=line\n"
1534 : "z.b.c=12.72\n"
1535 1 : ;
1536 : }
1537 :
1538 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1539 : , advgetopt::line_continuation_t::line_continuation_unix
1540 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1541 : , advgetopt::COMMENT_SHELL
1542 2 : , advgetopt::SECTION_OPERATOR_C);
1543 :
1544 1 : CATCH_REQUIRE(setup.is_valid());
1545 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1546 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1547 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1548 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
1549 :
1550 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1551 :
1552 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1553 1 : CATCH_REQUIRE(file->get_errno() == 0);
1554 :
1555 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1556 1 : CATCH_REQUIRE(sections.size() == 4);
1557 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1558 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
1559 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1560 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
1561 :
1562 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
1563 :
1564 1 : CATCH_REQUIRE(file->has_parameter("a"));
1565 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1566 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
1567 1 : CATCH_REQUIRE(file->has_parameter("m"));
1568 1 : CATCH_REQUIRE(file->has_parameter("z"));
1569 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
1570 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
1571 :
1572 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
1573 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1574 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "122");
1575 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
1576 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
1577 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
1578 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
1579 : CATCH_END_SECTION()
1580 :
1581 10 : CATCH_START_SECTION("section operator c++ (::)")
1582 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-cpp");
1583 :
1584 : {
1585 2 : std::ofstream config_file;
1586 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1587 1 : CATCH_REQUIRE(config_file.good());
1588 : config_file <<
1589 : "# Auto-generated\n"
1590 : "a=color\n"
1591 : "a::b=red\n"
1592 : "a::b::c=122\n"
1593 : "m=size\n"
1594 : "z=edge\n"
1595 : "z::b=line\n"
1596 : "z::b::c=12.72\n"
1597 1 : ;
1598 : }
1599 :
1600 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1601 : , advgetopt::line_continuation_t::line_continuation_unix
1602 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1603 : , advgetopt::COMMENT_SHELL
1604 2 : , advgetopt::SECTION_OPERATOR_CPP);
1605 :
1606 1 : CATCH_REQUIRE(setup.is_valid());
1607 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1608 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1609 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1610 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_CPP);
1611 :
1612 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1613 :
1614 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1615 1 : CATCH_REQUIRE(file->get_errno() == 0);
1616 :
1617 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1618 1 : CATCH_REQUIRE(sections.size() == 4);
1619 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1620 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
1621 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1622 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
1623 :
1624 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
1625 :
1626 1 : CATCH_REQUIRE(file->has_parameter("a"));
1627 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1628 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
1629 1 : CATCH_REQUIRE(file->has_parameter("m"));
1630 1 : CATCH_REQUIRE(file->has_parameter("z"));
1631 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
1632 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
1633 :
1634 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
1635 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1636 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "122");
1637 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
1638 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
1639 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
1640 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
1641 : CATCH_END_SECTION()
1642 :
1643 10 : CATCH_START_SECTION("section operator block ({ ... })")
1644 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-block");
1645 :
1646 : {
1647 2 : std::ofstream config_file;
1648 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1649 1 : CATCH_REQUIRE(config_file.good());
1650 : config_file <<
1651 : "# Auto-generated\n"
1652 : "a=color\n"
1653 : "a {\n"
1654 : " b=red\n"
1655 : " b {\n"
1656 : " c=122\n"
1657 : " }\n"
1658 : "}\n"
1659 : "m=size\n"
1660 : "z=edge\n"
1661 : "z {\n"
1662 : " b {\n"
1663 : " c=12.72\n"
1664 : " }\n"
1665 : " b=line\n"
1666 : "}\n"
1667 1 : ;
1668 : }
1669 :
1670 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1671 : , advgetopt::line_continuation_t::line_continuation_unix
1672 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1673 : , advgetopt::COMMENT_SHELL
1674 2 : , advgetopt::SECTION_OPERATOR_BLOCK);
1675 :
1676 1 : CATCH_REQUIRE(setup.is_valid());
1677 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1678 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1679 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1680 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_BLOCK);
1681 :
1682 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1683 :
1684 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1685 1 : CATCH_REQUIRE(file->get_errno() == 0);
1686 :
1687 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1688 1 : CATCH_REQUIRE(sections.size() == 4);
1689 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1690 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
1691 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1692 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
1693 :
1694 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
1695 :
1696 1 : CATCH_REQUIRE(file->has_parameter("a"));
1697 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1698 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
1699 1 : CATCH_REQUIRE(file->has_parameter("m"));
1700 1 : CATCH_REQUIRE(file->has_parameter("z"));
1701 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
1702 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
1703 :
1704 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
1705 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1706 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "122");
1707 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
1708 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
1709 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
1710 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
1711 : CATCH_END_SECTION()
1712 :
1713 10 : CATCH_START_SECTION("section operator ini file ([...])")
1714 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-ini-file");
1715 :
1716 : {
1717 2 : std::ofstream config_file;
1718 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1719 1 : CATCH_REQUIRE(config_file.good());
1720 : config_file <<
1721 : "# Auto-generated\n"
1722 : "a=color\n"
1723 : "[a]\n"
1724 : "b=red\n"
1725 : "b-c=122\n"
1726 : "[]\n"
1727 : "m=size\n"
1728 : "z=edge\n"
1729 : "[z] # we allow comments here\n"
1730 : "b=line\n"
1731 : "b-c=12.72\n"
1732 : "[p]#nospacenecessary\n"
1733 : "b=comment\n"
1734 : "b-c=allowed\n"
1735 1 : ;
1736 : }
1737 :
1738 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1739 : , advgetopt::line_continuation_t::line_continuation_unix
1740 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1741 : , advgetopt::COMMENT_SHELL
1742 2 : , advgetopt::SECTION_OPERATOR_INI_FILE);
1743 :
1744 1 : CATCH_REQUIRE(setup.is_valid());
1745 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1746 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1747 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1748 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_INI_FILE);
1749 :
1750 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1751 :
1752 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1753 1 : CATCH_REQUIRE(file->get_errno() == 0);
1754 :
1755 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1756 1 : CATCH_REQUIRE(sections.size() == 3);
1757 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1758 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1759 1 : CATCH_REQUIRE(sections.find("p") != sections.end());
1760 :
1761 1 : CATCH_REQUIRE(file->get_parameters().size() == 9);
1762 :
1763 1 : CATCH_REQUIRE(file->has_parameter("a"));
1764 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1765 1 : CATCH_REQUIRE(file->has_parameter("a::b-c"));
1766 1 : CATCH_REQUIRE(file->has_parameter("m"));
1767 1 : CATCH_REQUIRE(file->has_parameter("z"));
1768 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
1769 1 : CATCH_REQUIRE(file->has_parameter("z::b-c"));
1770 1 : CATCH_REQUIRE(file->has_parameter("p::b"));
1771 1 : CATCH_REQUIRE(file->has_parameter("p::b-c"));
1772 :
1773 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
1774 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1775 1 : CATCH_REQUIRE(file->get_parameter("a::b-c") == "122");
1776 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
1777 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
1778 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
1779 1 : CATCH_REQUIRE(file->get_parameter("z::b-c") == "12.72");
1780 1 : CATCH_REQUIRE(file->get_parameter("p::b") == "comment");
1781 1 : CATCH_REQUIRE(file->get_parameter("p::b-c") == "allowed");
1782 : CATCH_END_SECTION()
1783 :
1784 10 : CATCH_START_SECTION("section operator ini-file & c++")
1785 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("section-operator", "section-double");
1786 :
1787 : {
1788 2 : std::ofstream config_file;
1789 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1790 1 : CATCH_REQUIRE(config_file.good());
1791 : config_file <<
1792 : "# Auto-generated\n"
1793 : "[a]\n"
1794 : "b=red\n"
1795 : "b::c=209\n"
1796 : "::h=high\n"
1797 : "m=size\n"
1798 : "[z]\n"
1799 : "z=edge\n"
1800 : "::b=line\n"
1801 : "z::b::c=17.92\n"
1802 1 : ;
1803 : }
1804 :
1805 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1806 : , advgetopt::line_continuation_t::line_continuation_unix
1807 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1808 : , advgetopt::COMMENT_SHELL
1809 2 : , advgetopt::SECTION_OPERATOR_INI_FILE | advgetopt::SECTION_OPERATOR_CPP);
1810 :
1811 1 : CATCH_REQUIRE(setup.is_valid());
1812 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
1813 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1814 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1815 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_INI_FILE | advgetopt::SECTION_OPERATOR_CPP));
1816 :
1817 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1818 :
1819 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1820 1 : CATCH_REQUIRE(file->get_errno() == 0);
1821 :
1822 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1823 1 : CATCH_REQUIRE(sections.size() == 4);
1824 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
1825 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
1826 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
1827 1 : CATCH_REQUIRE(sections.find("z::z::b") != sections.end());
1828 :
1829 1 : CATCH_REQUIRE(file->get_parameters().size() == 7);
1830 :
1831 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
1832 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
1833 1 : CATCH_REQUIRE(file->has_parameter("h"));
1834 1 : CATCH_REQUIRE(file->has_parameter("a::m"));
1835 1 : CATCH_REQUIRE(file->has_parameter("z::z"));
1836 1 : CATCH_REQUIRE(file->has_parameter("b"));
1837 1 : CATCH_REQUIRE(file->has_parameter("z::z::b::c"));
1838 :
1839 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
1840 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "209");
1841 1 : CATCH_REQUIRE(file->get_parameter("h") == "high");
1842 1 : CATCH_REQUIRE(file->get_parameter("a::m") == "size");
1843 1 : CATCH_REQUIRE(file->get_parameter("z::z") == "edge");
1844 1 : CATCH_REQUIRE(file->get_parameter("b") == "line");
1845 1 : CATCH_REQUIRE(file->get_parameter("z::z::b::c") == "17.92");
1846 : CATCH_END_SECTION()
1847 5 : }
1848 :
1849 :
1850 :
1851 :
1852 3 : CATCH_TEST_CASE("save_config_file")
1853 : {
1854 2 : CATCH_START_SECTION("load update save")
1855 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("save-operation", "configuration");
1856 :
1857 : {
1858 2 : std::ofstream config_file;
1859 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
1860 1 : CATCH_REQUIRE(config_file.good());
1861 : config_file <<
1862 : "# Auto-generated\n"
1863 : "a=color\n"
1864 : "b=red\n"
1865 : "c=122\n"
1866 1 : ;
1867 : }
1868 :
1869 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
1870 : , advgetopt::line_continuation_t::line_continuation_single_line
1871 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1872 : , advgetopt::COMMENT_SHELL
1873 2 : , advgetopt::SECTION_OPERATOR_NONE);
1874 :
1875 1 : CATCH_REQUIRE(setup.is_valid());
1876 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1877 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1878 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
1879 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1880 :
1881 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
1882 :
1883 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
1884 1 : CATCH_REQUIRE(file->get_errno() == 0);
1885 :
1886 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
1887 1 : CATCH_REQUIRE(sections.empty());
1888 :
1889 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
1890 :
1891 1 : CATCH_REQUIRE(file->has_parameter("a"));
1892 1 : CATCH_REQUIRE(file->has_parameter("b"));
1893 1 : CATCH_REQUIRE(file->has_parameter("c"));
1894 :
1895 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
1896 1 : CATCH_REQUIRE(file->get_parameter("b") == "red");
1897 1 : CATCH_REQUIRE(file->get_parameter("c") == "122");
1898 :
1899 1 : CATCH_REQUIRE(file->save_configuration());
1900 :
1901 : // no backup since there was no modification so the save did nothing
1902 : //
1903 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".bak").c_str(), F_OK) != 0);
1904 :
1905 1 : file->set_parameter(std::string(), "a", "size");
1906 1 : file->set_parameter(std::string(), "b", "tall");
1907 1 : file->set_parameter(std::string(), "c", "1920");
1908 :
1909 1 : CATCH_REQUIRE(file->save_configuration());
1910 :
1911 1 : CATCH_REQUIRE(access((SNAP_CATCH2_NAMESPACE::g_config_filename + ".bak").c_str(), F_OK) == 0);
1912 :
1913 2 : std::string const new_name(SNAP_CATCH2_NAMESPACE::g_config_filename + ".conf2");
1914 1 : rename(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str(), new_name.c_str());
1915 :
1916 : advgetopt::conf_file_setup setup2(new_name
1917 : , advgetopt::line_continuation_t::line_continuation_single_line
1918 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
1919 : , advgetopt::COMMENT_SHELL
1920 2 : , advgetopt::SECTION_OPERATOR_NONE);
1921 :
1922 1 : CATCH_REQUIRE(setup2.is_valid());
1923 1 : CATCH_REQUIRE(setup2.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
1924 1 : CATCH_REQUIRE(setup2.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
1925 1 : CATCH_REQUIRE(setup2.get_comment() == advgetopt::COMMENT_SHELL);
1926 1 : CATCH_REQUIRE(setup2.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
1927 :
1928 2 : advgetopt::conf_file::pointer_t file2(advgetopt::conf_file::get_conf_file(setup2));
1929 :
1930 1 : CATCH_REQUIRE(file2->get_setup().get_config_url() == setup2.get_config_url());
1931 1 : CATCH_REQUIRE(file2->get_errno() == 0);
1932 :
1933 1 : CATCH_REQUIRE(file->get_sections().empty());
1934 :
1935 1 : CATCH_REQUIRE(file2->get_parameters().size() == 3);
1936 :
1937 1 : CATCH_REQUIRE(file2->has_parameter("a"));
1938 1 : CATCH_REQUIRE(file2->has_parameter("b"));
1939 1 : CATCH_REQUIRE(file2->has_parameter("c"));
1940 :
1941 1 : CATCH_REQUIRE(file2->get_parameter("a") == "size");
1942 1 : CATCH_REQUIRE(file2->get_parameter("b") == "tall");
1943 1 : CATCH_REQUIRE(file2->get_parameter("c") == "1920");
1944 : CATCH_END_SECTION()
1945 1 : }
1946 :
1947 :
1948 :
1949 :
1950 :
1951 :
1952 :
1953 4 : CATCH_TEST_CASE("invalid_configuration_setup", "[config][getopt][invalid]")
1954 : {
1955 4 : CATCH_START_SECTION("Empty Filename")
1956 1 : CATCH_REQUIRE_THROWS_MATCHES(
1957 : advgetopt::conf_file_setup(
1958 : std::string()
1959 : , static_cast<advgetopt::line_continuation_t>(rand())
1960 : , rand()
1961 : , rand()
1962 : , rand())
1963 : , advgetopt::getopt_exception_invalid
1964 : , Catch::Matchers::ExceptionMessage(
1965 : "trying to load a configuration file using an empty filename."));
1966 : CATCH_END_SECTION()
1967 :
1968 4 : CATCH_START_SECTION("Invalid Line Continuation")
1969 6 : for(int count(0); count < 5; ++count)
1970 : {
1971 5 : advgetopt::line_continuation_t lc(advgetopt::line_continuation_t::line_continuation_unix);
1972 0 : do
1973 : {
1974 5 : lc = static_cast<advgetopt::line_continuation_t>(rand());
1975 : }
1976 : while(lc >= advgetopt::line_continuation_t::line_continuation_single_line
1977 5 : && lc <= advgetopt::line_continuation_t::line_continuation_semicolon);
1978 :
1979 : advgetopt::conf_file_setup setup(
1980 : "/etc/advgetopt/system.conf"
1981 : , lc // <- this is invalid
1982 5 : , rand() & advgetopt::ASSIGNMENT_OPERATOR_MASK
1983 5 : , rand() & advgetopt::COMMENT_MASK
1984 20 : , rand() & advgetopt::SECTION_OPERATOR_MASK);
1985 :
1986 5 : CATCH_REQUIRE_FALSE(setup.is_valid());
1987 :
1988 5 : CATCH_REQUIRE_THROWS_MATCHES(
1989 : setup.get_config_url()
1990 : , advgetopt::getopt_exception_logic
1991 : , Catch::Matchers::ExceptionMessage(
1992 : "unexpected line continuation."));
1993 : }
1994 : CATCH_END_SECTION()
1995 2 : }
1996 :
1997 :
1998 :
1999 :
2000 :
2001 :
2002 :
2003 3 : CATCH_TEST_CASE("config_reload_invalid_setup")
2004 : {
2005 2 : CATCH_START_SECTION("Load a file, update it, verify it does not get reloaded")
2006 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-reload", "load-twice-wrong-parameters");
2007 :
2008 : {
2009 2 : std::ofstream config_file;
2010 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2011 1 : CATCH_REQUIRE(config_file.good());
2012 : config_file <<
2013 : "# Auto-generated\n"
2014 : "duplicates=work\n"
2015 : "varying=parameters\n"
2016 : "however=is\n"
2017 : "not=valid\n"
2018 1 : ;
2019 : }
2020 :
2021 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2022 : , advgetopt::line_continuation_t::line_continuation_single_line
2023 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2024 : , advgetopt::COMMENT_SHELL
2025 2 : , advgetopt::SECTION_OPERATOR_NONE);
2026 :
2027 1 : CATCH_REQUIRE(setup.is_valid());
2028 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_single_line);
2029 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2030 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2031 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2032 :
2033 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2034 :
2035 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2036 1 : CATCH_REQUIRE(file->get_errno() == 0);
2037 1 : CATCH_REQUIRE(file->get_sections().empty());
2038 1 : CATCH_REQUIRE(file->get_parameters().size() == 4);
2039 :
2040 1 : CATCH_REQUIRE(file->has_parameter("duplicates"));
2041 1 : CATCH_REQUIRE(file->has_parameter("varying"));
2042 1 : CATCH_REQUIRE(file->has_parameter("however"));
2043 1 : CATCH_REQUIRE(file->has_parameter("not"));
2044 :
2045 1 : CATCH_REQUIRE(file->get_parameter("duplicates") == "work");
2046 1 : CATCH_REQUIRE(file->get_parameter("varying") == "parameters");
2047 1 : CATCH_REQUIRE(file->get_parameter("however") == "is");
2048 1 : CATCH_REQUIRE(file->get_parameter("not") == "valid");
2049 :
2050 : // "reloading" that very same file but with the "wrong" parameters
2051 : // fails
2052 : //
2053 7 : for(int lc(static_cast<int>(advgetopt::line_continuation_t::line_continuation_single_line));
2054 7 : lc <= static_cast<int>(advgetopt::line_continuation_t::line_continuation_semicolon);
2055 : ++lc)
2056 : {
2057 6 : if(static_cast<advgetopt::line_continuation_t>(lc) == advgetopt::line_continuation_t::line_continuation_single_line)
2058 : {
2059 1 : continue;
2060 : }
2061 :
2062 45 : for(advgetopt::assignment_operator_t ao(0);
2063 45 : ao <= advgetopt::ASSIGNMENT_OPERATOR_MASK;
2064 : ++ao)
2065 : {
2066 40 : if(ao == advgetopt::ASSIGNMENT_OPERATOR_EQUAL)
2067 : {
2068 5 : continue;
2069 : }
2070 :
2071 280 : for(advgetopt::comment_t c(0);
2072 280 : c < advgetopt::COMMENT_MASK;
2073 : ++c)
2074 : {
2075 245 : if(c == advgetopt::COMMENT_SHELL)
2076 : {
2077 35 : continue;
2078 : }
2079 :
2080 3360 : for(advgetopt::section_operator_t so(0);
2081 3360 : so < advgetopt::SECTION_OPERATOR_MASK;
2082 : ++so)
2083 : {
2084 3150 : if(c == advgetopt::SECTION_OPERATOR_NONE)
2085 : {
2086 525 : continue;
2087 : }
2088 :
2089 : advgetopt::conf_file_setup different_setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2090 : , static_cast<advgetopt::line_continuation_t>(lc)
2091 : , ao
2092 : , c
2093 5250 : , so);
2094 :
2095 2625 : CATCH_REQUIRE_THROWS_MATCHES(
2096 : advgetopt::conf_file::get_conf_file(different_setup)
2097 : , advgetopt::getopt_exception_logic
2098 : , Catch::Matchers::ExceptionMessage(
2099 : "trying to load configuration file \""
2100 : + different_setup.get_config_url()
2101 : + "\" but an existing configuration file with the same name was loaded with URL: \""
2102 : + setup.get_config_url()
2103 : + "\"."));
2104 : }
2105 : }
2106 : }
2107 : }
2108 : CATCH_END_SECTION()
2109 1 : }
2110 :
2111 :
2112 3 : CATCH_TEST_CASE("missing_configuration_file", "[config][getopt][invalid]")
2113 : {
2114 2 : CATCH_START_SECTION("Create a conf_file without the file")
2115 6 : for(int count(0); count < 5; ++count)
2116 : {
2117 5 : int const id(rand());
2118 10 : std::string const name("delete-file-" + std::to_string(id));
2119 :
2120 5 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("delete", name);
2121 :
2122 : {
2123 10 : std::ofstream config_file;
2124 5 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2125 5 : CATCH_REQUIRE(config_file.good());
2126 : config_file <<
2127 : "# Auto-generated\n"
2128 : "param=optional\n"
2129 5 : ;
2130 : }
2131 :
2132 : // create the setup while the file still exists
2133 : //
2134 : advgetopt::conf_file_setup setup(
2135 : SNAP_CATCH2_NAMESPACE::g_config_filename
2136 : , advgetopt::line_continuation_t::line_continuation_unix
2137 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2138 : , advgetopt::COMMENT_SHELL
2139 10 : , advgetopt::SECTION_OPERATOR_NONE);
2140 :
2141 : // now unlink() that file
2142 : //
2143 5 : unlink(SNAP_CATCH2_NAMESPACE::g_config_filename.c_str());
2144 :
2145 : // still valid since we do not check again after the
2146 : // constructor ran
2147 : //
2148 5 : CATCH_REQUIRE(setup.is_valid());
2149 5 : CATCH_REQUIRE(setup.get_filename() == SNAP_CATCH2_NAMESPACE::g_config_filename);
2150 5 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2151 5 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2152 5 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2153 5 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_NONE);
2154 :
2155 : // so when trying to create the conf_file object it fails
2156 : // opening the file
2157 : //
2158 10 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2159 5 : CATCH_REQUIRE(file->get_errno() == ENOENT);
2160 : }
2161 : CATCH_END_SECTION()
2162 1 : }
2163 :
2164 :
2165 11 : CATCH_TEST_CASE("invalid_sections")
2166 : {
2167 18 : CATCH_START_SECTION("variable name cannot start with a period when C operator is active")
2168 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "period-name");
2169 :
2170 : {
2171 2 : std::ofstream config_file;
2172 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2173 1 : CATCH_REQUIRE(config_file.good());
2174 : config_file <<
2175 : "# Auto-generated\n"
2176 : "a=color\n"
2177 : "a..b=red\n"
2178 : ".a.b.c=122\n"
2179 : "m=size\n"
2180 : "z=edge\n"
2181 : "z.b=line\n"
2182 : "z..b.c=12.72\n"
2183 1 : ;
2184 : }
2185 :
2186 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2187 : , advgetopt::line_continuation_t::line_continuation_unix
2188 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2189 : , advgetopt::COMMENT_SHELL
2190 2 : , advgetopt::SECTION_OPERATOR_C);
2191 :
2192 1 : CATCH_REQUIRE(setup.is_valid());
2193 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2194 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2195 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2196 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
2197 :
2198 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2199 : "error: option name \".a.b.c\" cannot start with"
2200 1 : " a period (.).");
2201 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2202 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2203 :
2204 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2205 1 : CATCH_REQUIRE(file->get_errno() == 0);
2206 :
2207 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2208 1 : CATCH_REQUIRE(sections.size() == 3);
2209 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
2210 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
2211 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
2212 :
2213 1 : CATCH_REQUIRE(file->get_parameters().size() == 6);
2214 :
2215 1 : CATCH_REQUIRE(file->has_parameter("a"));
2216 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
2217 1 : CATCH_REQUIRE(file->has_parameter("m"));
2218 1 : CATCH_REQUIRE(file->has_parameter("z"));
2219 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
2220 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
2221 :
2222 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2223 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
2224 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
2225 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
2226 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
2227 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
2228 : CATCH_END_SECTION()
2229 :
2230 18 : CATCH_START_SECTION("two section operators one after another can cause trouble")
2231 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "name-period-cpp-name");
2232 :
2233 : {
2234 2 : std::ofstream config_file;
2235 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2236 1 : CATCH_REQUIRE(config_file.good());
2237 : config_file <<
2238 : "# Auto-generated\n"
2239 : "a=color\n"
2240 : "a..b=red\n"
2241 : "a.::b.c=122\n"
2242 : "m=size\n"
2243 : "z=edge\n"
2244 : "z.b=line\n"
2245 : "z..b.c=12.72\n"
2246 1 : ;
2247 : }
2248 :
2249 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2250 : , advgetopt::line_continuation_t::line_continuation_unix
2251 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2252 : , advgetopt::COMMENT_SHELL
2253 2 : , advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_CPP);
2254 :
2255 1 : CATCH_REQUIRE(setup.is_valid());
2256 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2257 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2258 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2259 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_CPP));
2260 :
2261 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2262 : "error: option name \"a.::b.c\" cannot start with"
2263 1 : " a scope operator (::).");
2264 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2265 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2266 :
2267 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2268 1 : CATCH_REQUIRE(file->get_errno() == 0);
2269 :
2270 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2271 1 : CATCH_REQUIRE(sections.size() == 3);
2272 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
2273 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
2274 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
2275 :
2276 1 : CATCH_REQUIRE(file->get_parameters().size() == 6);
2277 :
2278 1 : CATCH_REQUIRE(file->has_parameter("a"));
2279 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
2280 1 : CATCH_REQUIRE(file->has_parameter("m"));
2281 1 : CATCH_REQUIRE(file->has_parameter("z"));
2282 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
2283 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
2284 :
2285 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2286 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
2287 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
2288 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
2289 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
2290 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
2291 : CATCH_END_SECTION()
2292 :
2293 18 : CATCH_START_SECTION("section operator cannot appear at the end")
2294 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "name-period-name-cpp");
2295 :
2296 : {
2297 2 : std::ofstream config_file;
2298 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2299 1 : CATCH_REQUIRE(config_file.good());
2300 : config_file <<
2301 : "# Auto-generated\n"
2302 : "a=color\n"
2303 : "a..b=red\n"
2304 : "a.b.c::=122\n"
2305 : "m=size\n"
2306 : "z=edge\n"
2307 : "z.b=line\n"
2308 : "z..b.c=12.72\n"
2309 1 : ;
2310 : }
2311 :
2312 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2313 : , advgetopt::line_continuation_t::line_continuation_unix
2314 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2315 : , advgetopt::COMMENT_SHELL
2316 2 : , advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_CPP);
2317 :
2318 1 : CATCH_REQUIRE(setup.is_valid());
2319 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2320 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2321 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2322 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_CPP));
2323 :
2324 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2325 : "error: option name \"a.b.c::\" cannot end with a"
2326 1 : " section operator or be empty.");
2327 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2328 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2329 :
2330 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2331 1 : CATCH_REQUIRE(file->get_errno() == 0);
2332 :
2333 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2334 1 : CATCH_REQUIRE(sections.size() == 3);
2335 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
2336 1 : CATCH_REQUIRE(sections.find("z") != sections.end());
2337 1 : CATCH_REQUIRE(sections.find("z::b") != sections.end());
2338 :
2339 1 : CATCH_REQUIRE(file->get_parameters().size() == 6);
2340 :
2341 1 : CATCH_REQUIRE(file->has_parameter("a"));
2342 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
2343 1 : CATCH_REQUIRE(file->has_parameter("m"));
2344 1 : CATCH_REQUIRE(file->has_parameter("z"));
2345 1 : CATCH_REQUIRE(file->has_parameter("z::b"));
2346 1 : CATCH_REQUIRE(file->has_parameter("z::b::c"));
2347 :
2348 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2349 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
2350 1 : CATCH_REQUIRE(file->get_parameter("m") == "size");
2351 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
2352 1 : CATCH_REQUIRE(file->get_parameter("z::b") == "line");
2353 1 : CATCH_REQUIRE(file->get_parameter("z::b::c") == "12.72");
2354 : CATCH_END_SECTION()
2355 :
2356 18 : CATCH_START_SECTION("sections not allowed")
2357 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "section-not-allowed");
2358 :
2359 : {
2360 2 : std::ofstream config_file;
2361 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2362 1 : CATCH_REQUIRE(config_file.good());
2363 : config_file <<
2364 : "# Auto-generated\n"
2365 : "a=color\n"
2366 : "a::b=red\n"
2367 : "m.n=size\n"
2368 : "z=edge\n"
2369 1 : ;
2370 : }
2371 :
2372 : // no errors here since we do not detect the sections in this case
2373 : //
2374 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2375 : , advgetopt::line_continuation_t::line_continuation_unix
2376 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2377 : , advgetopt::COMMENT_SHELL
2378 2 : , advgetopt::SECTION_OPERATOR_NONE);
2379 :
2380 1 : CATCH_REQUIRE(setup.is_valid());
2381 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2382 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2383 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2384 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_NONE));
2385 :
2386 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2387 : "error: parameter \"a::b\" on line 3 in configuration file \""
2388 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
2389 2 : + "\" includes a character not acceptable for a section or"
2390 1 : " parameter name (controls, space, quotes, and \";#/=:?+\\\".");
2391 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2392 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2393 :
2394 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2395 1 : CATCH_REQUIRE(file->get_errno() == 0);
2396 :
2397 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2398 1 : CATCH_REQUIRE(sections.empty());
2399 :
2400 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
2401 :
2402 1 : CATCH_REQUIRE(file->has_parameter("a"));
2403 1 : CATCH_REQUIRE_FALSE(file->has_parameter("a::b"));
2404 1 : CATCH_REQUIRE(file->has_parameter("m.n"));
2405 1 : CATCH_REQUIRE(file->has_parameter("z"));
2406 :
2407 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2408 1 : CATCH_REQUIRE(file->get_parameter("a::b") == std::string());
2409 1 : CATCH_REQUIRE(file->get_parameter("m.n") == "size");
2410 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
2411 :
2412 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2413 : "error: option name \"blue::shepard\" cannot be added to"
2414 : " section \"j::k\" because there is no section support"
2415 1 : " for this configuration file.");
2416 1 : file->set_parameter("j::k", "blue::shepard", "2001");
2417 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2418 : CATCH_END_SECTION()
2419 :
2420 18 : CATCH_START_SECTION("invalid characters in names")
2421 : std::string const bad_chars(
2422 : "\x01\x02\x03\x04\x05\x06\x07"
2423 : "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
2424 : "\x10\x11\x12\x13\x14\x15\x16\x17"
2425 : "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
2426 : "\x20"
2427 : "'\";#/=:?+\\"
2428 2 : );
2429 43 : for(auto c : bad_chars)
2430 : {
2431 : // white spaces get removed from the line so we cannot test
2432 : // them in this way
2433 : //
2434 42 : if(std::iswspace(c))
2435 : {
2436 6 : continue;
2437 : }
2438 72 : std::string bc;
2439 36 : bc += c;
2440 :
2441 144 : for(int pos(0); pos < 3; ++pos)
2442 : {
2443 216 : std::string spos("undefined");
2444 216 : std::string bad_char("undefined");
2445 108 : switch(pos)
2446 : {
2447 : case 0:
2448 36 : spos = "start";
2449 36 : bad_char = bc + "bad-char";
2450 36 : break;
2451 :
2452 : case 1:
2453 36 : spos = "middle";
2454 36 : bad_char = "bad" + bc + "char";
2455 36 : break;
2456 :
2457 : case 2:
2458 36 : spos = "end";
2459 36 : bad_char = "bad-char" + bc;
2460 36 : break;
2461 :
2462 : }
2463 108 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-characters", "bad-character-" + std::to_string(static_cast<int>(c)) + "-" + spos);
2464 :
2465 : {
2466 216 : std::ofstream config_file;
2467 108 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2468 108 : CATCH_REQUIRE(config_file.good());
2469 108 : char op(c == '=' ? ':' : '=');
2470 : config_file <<
2471 108 : "good" << op << "red\n"
2472 216 : << bad_char << op << "color\n" // <-- bad char
2473 216 : "fine" << op << "param\n";
2474 : ;
2475 : }
2476 :
2477 : // no errors here since we do not detect the sections in this case
2478 : //
2479 : advgetopt::assignment_operator_t as(c == '='
2480 : ? advgetopt::ASSIGNMENT_OPERATOR_COLON
2481 108 : : advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2482 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2483 : , advgetopt::line_continuation_t::line_continuation_unix
2484 : , as
2485 : , advgetopt::COMMENT_NONE
2486 216 : , advgetopt::SECTION_OPERATOR_NONE);
2487 :
2488 108 : CATCH_REQUIRE(setup.is_valid());
2489 108 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2490 108 : CATCH_REQUIRE(setup.get_assignment_operator() == as);
2491 108 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_NONE);
2492 108 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_NONE));
2493 :
2494 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2495 : "error: parameter \""
2496 216 : + bad_char
2497 216 : + "\" on line 2 in configuration file \""
2498 216 : + SNAP_CATCH2_NAMESPACE::g_config_filename
2499 216 : + "\" includes a character not acceptable for a section or"
2500 108 : " parameter name (controls, space, quotes, and \";#/=:?+\\\".");
2501 216 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2502 :
2503 108 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2504 108 : CATCH_REQUIRE(file->get_errno() == 0);
2505 :
2506 216 : advgetopt::conf_file::sections_t sections(file->get_sections());
2507 108 : CATCH_REQUIRE(sections.empty());
2508 :
2509 108 : CATCH_REQUIRE(file->get_parameters().size() == 2);
2510 :
2511 108 : CATCH_REQUIRE(file->has_parameter("good"));
2512 108 : CATCH_REQUIRE_FALSE(file->has_parameter(bad_char));
2513 108 : CATCH_REQUIRE(file->has_parameter("fine"));
2514 :
2515 108 : CATCH_REQUIRE(file->get_parameter("good") == "red");
2516 108 : CATCH_REQUIRE(file->get_parameter(bad_char) == std::string());
2517 108 : CATCH_REQUIRE(file->get_parameter("fine") == "param");
2518 : }
2519 : }
2520 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2521 : CATCH_END_SECTION()
2522 :
2523 18 : CATCH_START_SECTION("too many sections")
2524 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "too-many-sections");
2525 :
2526 : {
2527 2 : std::ofstream config_file;
2528 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2529 1 : CATCH_REQUIRE(config_file.good());
2530 : config_file <<
2531 : "# Auto-generated\n"
2532 : "a=color\n"
2533 : "a::b=red\n"
2534 : "m.n.o=size\n"
2535 : "z=edge\n"
2536 1 : ;
2537 : }
2538 :
2539 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2540 : , advgetopt::line_continuation_t::line_continuation_unix
2541 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2542 : , advgetopt::COMMENT_SHELL
2543 2 : , advgetopt::SECTION_OPERATOR_CPP | advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_ONE_SECTION);
2544 :
2545 1 : CATCH_REQUIRE(setup.is_valid());
2546 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2547 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2548 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2549 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_CPP | advgetopt::SECTION_OPERATOR_C | advgetopt::SECTION_OPERATOR_ONE_SECTION));
2550 :
2551 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2552 : "error: option name \"m.n.o\" cannot be added to section"
2553 : " \"m::n\" because this configuration only accepts one"
2554 1 : " section level.");
2555 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2556 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2557 :
2558 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2559 1 : CATCH_REQUIRE(file->get_errno() == 0);
2560 :
2561 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2562 1 : CATCH_REQUIRE(sections.size() == 1);
2563 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
2564 :
2565 1 : CATCH_REQUIRE(file->get_parameters().size() == 3);
2566 :
2567 1 : CATCH_REQUIRE(file->has_parameter("a"));
2568 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
2569 1 : CATCH_REQUIRE(file->has_parameter("z"));
2570 :
2571 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2572 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
2573 1 : CATCH_REQUIRE(file->get_parameter("z") == "edge");
2574 : CATCH_END_SECTION()
2575 :
2576 18 : CATCH_START_SECTION("all '{' were not closed")
2577 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "unclosed-brackets");
2578 :
2579 : {
2580 2 : std::ofstream config_file;
2581 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2582 1 : CATCH_REQUIRE(config_file.good());
2583 : config_file <<
2584 : "# Auto-generated\n"
2585 : "colors {\n"
2586 : " b=red\n"
2587 : " c=blue\n"
2588 1 : ;
2589 : }
2590 :
2591 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2592 : , advgetopt::line_continuation_t::line_continuation_unix
2593 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2594 : , advgetopt::COMMENT_SHELL
2595 2 : , advgetopt::SECTION_OPERATOR_BLOCK);
2596 :
2597 1 : CATCH_REQUIRE(setup.is_valid());
2598 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2599 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2600 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2601 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_BLOCK);
2602 :
2603 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2604 : "error: unterminated `section { ... }`, the `}` is missing"
2605 : " in configuration file "
2606 1 : "\"" + SNAP_CATCH2_NAMESPACE::g_config_filename + "\".");
2607 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2608 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2609 :
2610 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2611 1 : CATCH_REQUIRE(file->get_errno() == 0);
2612 :
2613 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2614 1 : CATCH_REQUIRE(sections.size() == 1);
2615 1 : CATCH_REQUIRE(sections.find("colors") != sections.end());
2616 :
2617 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
2618 :
2619 1 : CATCH_REQUIRE(file->has_parameter("colors::b"));
2620 1 : CATCH_REQUIRE(file->has_parameter("colors::c"));
2621 :
2622 1 : CATCH_REQUIRE(file->get_parameter("colors::b") == "red");
2623 1 : CATCH_REQUIRE(file->get_parameter("colors::c") == "blue");
2624 : CATCH_END_SECTION()
2625 :
2626 18 : CATCH_START_SECTION("data after ']' in INI file")
2627 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "additional-data");
2628 :
2629 : {
2630 2 : std::ofstream config_file;
2631 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2632 1 : CATCH_REQUIRE(config_file.good());
2633 : config_file <<
2634 : "# Auto-generated\n"
2635 : "[colors]\n"
2636 : "b=red\n"
2637 : "c=blue\n"
2638 : "\n"
2639 : "[sizes] comment\n" // <- missing the comment introducer
2640 : "q=1000\n"
2641 : "r=9999\n"
2642 1 : ;
2643 : }
2644 :
2645 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2646 : , advgetopt::line_continuation_t::line_continuation_unix
2647 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2648 : , advgetopt::COMMENT_SHELL
2649 2 : , advgetopt::SECTION_OPERATOR_INI_FILE);
2650 :
2651 1 : CATCH_REQUIRE(setup.is_valid());
2652 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2653 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2654 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2655 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_INI_FILE);
2656 :
2657 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2658 : "error: section names in configuration files cannot be followed by anything other than spaces in"
2659 : " \"[sizes] comment\" on line 6 from configuration file \""
2660 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
2661 1 : + "\".");
2662 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2663 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2664 :
2665 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2666 1 : CATCH_REQUIRE(file->get_errno() == 0);
2667 :
2668 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2669 1 : CATCH_REQUIRE(sections.size() == 1);
2670 1 : CATCH_REQUIRE(sections.find("colors") != sections.end());
2671 :
2672 1 : CATCH_REQUIRE(file->get_parameters().size() == 4);
2673 :
2674 1 : CATCH_REQUIRE(file->has_parameter("colors::b"));
2675 1 : CATCH_REQUIRE(file->has_parameter("colors::c"));
2676 1 : CATCH_REQUIRE(file->has_parameter("colors::q"));
2677 1 : CATCH_REQUIRE(file->has_parameter("colors::r"));
2678 :
2679 1 : CATCH_REQUIRE(file->get_parameter("colors::b") == "red");
2680 1 : CATCH_REQUIRE(file->get_parameter("colors::c") == "blue");
2681 1 : CATCH_REQUIRE(file->get_parameter("colors::q") == "1000");
2682 1 : CATCH_REQUIRE(file->get_parameter("colors::r") == "9999");
2683 : CATCH_END_SECTION()
2684 :
2685 18 : CATCH_START_SECTION("INI file section inside a block is not allowed")
2686 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-section-operator", "ini-inside-block");
2687 :
2688 : {
2689 2 : std::ofstream config_file;
2690 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2691 1 : CATCH_REQUIRE(config_file.good());
2692 : config_file <<
2693 : "# Auto-generated\n"
2694 : "[colors]\n"
2695 : "b=red\n"
2696 : "c=blue\n"
2697 : "\n"
2698 : "block {\n"
2699 : " b = block data\n"
2700 : " f = filename\n"
2701 : " [sizes]\n" // <-- INI section inside a block not allowed
2702 : " q=1000\n"
2703 : " r=9999\n"
2704 : "}\n"
2705 1 : ;
2706 : }
2707 :
2708 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2709 : , advgetopt::line_continuation_t::line_continuation_unix
2710 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2711 : , advgetopt::COMMENT_SHELL
2712 2 : , advgetopt::SECTION_OPERATOR_BLOCK | advgetopt::SECTION_OPERATOR_INI_FILE);
2713 :
2714 1 : CATCH_REQUIRE(setup.is_valid());
2715 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2716 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2717 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2718 1 : CATCH_REQUIRE(setup.get_section_operator() == (advgetopt::SECTION_OPERATOR_BLOCK | advgetopt::SECTION_OPERATOR_INI_FILE));
2719 :
2720 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2721 : "error: `[...]` sections can't be used within a `section"
2722 : " { ... }` on line 9 from configuration file \""
2723 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
2724 1 : + "\".");
2725 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2726 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2727 :
2728 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2729 1 : CATCH_REQUIRE(file->get_errno() == 0);
2730 :
2731 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2732 1 : CATCH_REQUIRE(sections.size() == 2);
2733 1 : CATCH_REQUIRE(sections.find("colors") != sections.end());
2734 1 : CATCH_REQUIRE(sections.find("colors::block") != sections.end());
2735 :
2736 1 : CATCH_REQUIRE(file->get_parameters().size() == 6);
2737 :
2738 1 : CATCH_REQUIRE(file->has_parameter("colors::b"));
2739 1 : CATCH_REQUIRE(file->has_parameter("colors::c"));
2740 1 : CATCH_REQUIRE(file->has_parameter("colors::block::b"));
2741 1 : CATCH_REQUIRE(file->has_parameter("colors::block::f"));
2742 1 : CATCH_REQUIRE(file->has_parameter("colors::block::q"));
2743 1 : CATCH_REQUIRE(file->has_parameter("colors::block::r"));
2744 :
2745 1 : CATCH_REQUIRE(file->get_parameter("colors::b") == "red");
2746 1 : CATCH_REQUIRE(file->get_parameter("colors::c") == "blue");
2747 1 : CATCH_REQUIRE(file->get_parameter("colors::block::b") == "block data");
2748 1 : CATCH_REQUIRE(file->get_parameter("colors::block::f") == "filename");
2749 1 : CATCH_REQUIRE(file->get_parameter("colors::block::q") == "1000");
2750 1 : CATCH_REQUIRE(file->get_parameter("colors::block::r") == "9999");
2751 : CATCH_END_SECTION()
2752 9 : }
2753 :
2754 :
2755 :
2756 7 : CATCH_TEST_CASE("invalid_variable_name")
2757 : {
2758 10 : CATCH_START_SECTION("empty variable name")
2759 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "name-missing");
2760 :
2761 : {
2762 2 : std::ofstream config_file;
2763 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2764 1 : CATCH_REQUIRE(config_file.good());
2765 : config_file <<
2766 : "# Auto-generated\n"
2767 : "=color\n" // <-- name missing
2768 : "a..b=red\n"
2769 : "a.b.c=142\n"
2770 1 : ;
2771 : }
2772 :
2773 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2774 : , advgetopt::line_continuation_t::line_continuation_unix
2775 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2776 : , advgetopt::COMMENT_SHELL
2777 2 : , advgetopt::SECTION_OPERATOR_C);
2778 :
2779 1 : CATCH_REQUIRE(setup.is_valid());
2780 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2781 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2782 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2783 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
2784 :
2785 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2786 : "error: no option name in \"=color\""
2787 : " on line 2 from configuration file \""
2788 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
2789 1 : + "\", missing name before the assignment operator?");
2790 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2791 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2792 :
2793 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2794 1 : CATCH_REQUIRE(file->get_errno() == 0);
2795 :
2796 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2797 1 : CATCH_REQUIRE(sections.size() == 2);
2798 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
2799 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
2800 :
2801 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
2802 :
2803 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
2804 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
2805 :
2806 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
2807 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "142");
2808 : CATCH_END_SECTION()
2809 :
2810 10 : CATCH_START_SECTION("empty variable name after section name")
2811 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "section-and-name-missing");
2812 :
2813 : {
2814 2 : std::ofstream config_file;
2815 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2816 1 : CATCH_REQUIRE(config_file.good());
2817 : config_file <<
2818 : "# Auto-generated\n"
2819 : "a..b=red\n"
2820 : "a.b.=color\n" // <-- name missing after section name
2821 : "a.b.c=142\n"
2822 1 : ;
2823 : }
2824 :
2825 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2826 : , advgetopt::line_continuation_t::line_continuation_unix
2827 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2828 : , advgetopt::COMMENT_SHELL
2829 2 : , advgetopt::SECTION_OPERATOR_C);
2830 :
2831 1 : CATCH_REQUIRE(setup.is_valid());
2832 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2833 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2834 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2835 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
2836 :
2837 2 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2838 1 : "error: option name \"a.b.\" cannot end with a section operator or be empty.");
2839 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2840 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2841 :
2842 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2843 1 : CATCH_REQUIRE(file->get_errno() == 0);
2844 :
2845 2 : advgetopt::conf_file::sections_t sections(file->get_sections());
2846 1 : CATCH_REQUIRE(sections.size() == 2);
2847 1 : CATCH_REQUIRE(sections.find("a") != sections.end());
2848 1 : CATCH_REQUIRE(sections.find("a::b") != sections.end());
2849 :
2850 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
2851 :
2852 1 : CATCH_REQUIRE(file->has_parameter("a::b"));
2853 1 : CATCH_REQUIRE(file->has_parameter("a::b::c"));
2854 :
2855 1 : CATCH_REQUIRE(file->get_parameter("a::b") == "red");
2856 1 : CATCH_REQUIRE(file->get_parameter("a::b::c") == "142");
2857 : CATCH_END_SECTION()
2858 :
2859 10 : CATCH_START_SECTION("variable name starts with a dash")
2860 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "dash-name");
2861 :
2862 : {
2863 2 : std::ofstream config_file;
2864 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2865 1 : CATCH_REQUIRE(config_file.good());
2866 : config_file <<
2867 : "# Auto-generated\n"
2868 : "a=color\n"
2869 : "-bad-dash=reddish\n" // <-- name starts with '-'
2870 : "size=412\n"
2871 1 : ;
2872 : }
2873 :
2874 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2875 : , advgetopt::line_continuation_t::line_continuation_unix
2876 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2877 : , advgetopt::COMMENT_SHELL
2878 2 : , advgetopt::SECTION_OPERATOR_C);
2879 :
2880 1 : CATCH_REQUIRE(setup.is_valid());
2881 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2882 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2883 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2884 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
2885 :
2886 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2887 : "error: option names in configuration files cannot"
2888 : " start with a dash or an underscore in"
2889 : " \"-bad-dash=reddish\" on line 3 from configuration file \""
2890 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
2891 1 : + "\".");
2892 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2893 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2894 :
2895 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2896 1 : CATCH_REQUIRE(file->get_errno() == 0);
2897 :
2898 1 : CATCH_REQUIRE(file->get_sections().empty());
2899 :
2900 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
2901 :
2902 1 : CATCH_REQUIRE(file->has_parameter("a"));
2903 1 : CATCH_REQUIRE(file->has_parameter("size"));
2904 :
2905 1 : CATCH_REQUIRE(file->get_parameter("a") == "color");
2906 1 : CATCH_REQUIRE(file->get_parameter("size") == "412");
2907 : CATCH_END_SECTION()
2908 :
2909 10 : CATCH_START_SECTION("variable name starts with an underscore")
2910 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "underscore-name");
2911 :
2912 : {
2913 2 : std::ofstream config_file;
2914 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2915 1 : CATCH_REQUIRE(config_file.good());
2916 : config_file <<
2917 : "# Auto-generated\n"
2918 : "a_variable=color\n"
2919 : "_bad_underscore=reddish\n" // <-- name starts with '_'
2920 : "pos_and_size=412x33+32-18\n"
2921 1 : ;
2922 : }
2923 :
2924 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2925 : , advgetopt::line_continuation_t::line_continuation_unix
2926 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2927 : , advgetopt::COMMENT_SHELL
2928 2 : , advgetopt::SECTION_OPERATOR_C);
2929 :
2930 1 : CATCH_REQUIRE(setup.is_valid());
2931 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2932 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2933 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2934 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
2935 :
2936 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2937 : "error: option names in configuration files cannot"
2938 : " start with a dash or an underscore in"
2939 : " \"_bad_underscore=reddish\" on line 3 from configuration file \""
2940 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
2941 1 : + "\".");
2942 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
2943 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
2944 :
2945 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
2946 1 : CATCH_REQUIRE(file->get_errno() == 0);
2947 :
2948 1 : CATCH_REQUIRE(file->get_sections().empty());
2949 :
2950 1 : CATCH_REQUIRE(file->get_parameters().size() == 2);
2951 :
2952 1 : CATCH_REQUIRE(file->has_parameter("a-variable"));
2953 1 : CATCH_REQUIRE(file->has_parameter("pos-and-size"));
2954 :
2955 1 : CATCH_REQUIRE(file->get_parameter("a-variable") == "color");
2956 1 : CATCH_REQUIRE(file->get_parameter("pos-and-size") == "412x33+32-18");
2957 : CATCH_END_SECTION()
2958 :
2959 10 : CATCH_START_SECTION("variable name with spaces")
2960 1 : SNAP_CATCH2_NAMESPACE::init_tmp_dir("invalid-variable-name", "name-space-more-name");
2961 :
2962 : {
2963 2 : std::ofstream config_file;
2964 1 : config_file.open(SNAP_CATCH2_NAMESPACE::g_config_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
2965 1 : CATCH_REQUIRE(config_file.good());
2966 : config_file <<
2967 : "# Auto-generated\n"
2968 : "a variable=color\n"
2969 : "bad space=reddish\n"
2970 : "pos and size=412x33+32-18\n"
2971 1 : ;
2972 : }
2973 :
2974 : advgetopt::conf_file_setup setup(SNAP_CATCH2_NAMESPACE::g_config_filename
2975 : , advgetopt::line_continuation_t::line_continuation_unix
2976 : , advgetopt::ASSIGNMENT_OPERATOR_EQUAL
2977 : , advgetopt::COMMENT_SHELL
2978 2 : , advgetopt::SECTION_OPERATOR_C);
2979 :
2980 1 : CATCH_REQUIRE(setup.is_valid());
2981 1 : CATCH_REQUIRE(setup.get_line_continuation() == advgetopt::line_continuation_t::line_continuation_unix);
2982 1 : CATCH_REQUIRE(setup.get_assignment_operator() == advgetopt::ASSIGNMENT_OPERATOR_EQUAL);
2983 1 : CATCH_REQUIRE(setup.get_comment() == advgetopt::COMMENT_SHELL);
2984 1 : CATCH_REQUIRE(setup.get_section_operator() == advgetopt::SECTION_OPERATOR_C);
2985 :
2986 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2987 : "error: option name from \"a variable=color\" on line"
2988 : " 2 in configuration file \""
2989 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
2990 1 : + "\" cannot include a space, missing assignment operator?");
2991 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2992 : "error: option name from \"bad space=reddish\" on line"
2993 : " 3 in configuration file \""
2994 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
2995 1 : + "\" cannot include a space, missing assignment operator?");
2996 : SNAP_CATCH2_NAMESPACE::push_expected_log(
2997 : "error: option name from \"pos and size=412x33+32-18\" on line"
2998 : " 4 in configuration file \""
2999 2 : + SNAP_CATCH2_NAMESPACE::g_config_filename
3000 1 : + "\" cannot include a space, missing assignment operator?");
3001 2 : advgetopt::conf_file::pointer_t file(advgetopt::conf_file::get_conf_file(setup));
3002 1 : SNAP_CATCH2_NAMESPACE::expected_logs_stack_is_empty();
3003 :
3004 1 : CATCH_REQUIRE(file->get_setup().get_config_url() == setup.get_config_url());
3005 1 : CATCH_REQUIRE(file->get_errno() == 0);
3006 :
3007 1 : CATCH_REQUIRE(file->get_sections().empty());
3008 :
3009 1 : CATCH_REQUIRE(file->get_parameters().empty());
3010 : CATCH_END_SECTION()
3011 11 : }
3012 :
3013 :
3014 :
3015 :
3016 :
3017 : // vim: ts=4 sw=4 et
|