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