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