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