Toolbox snapshot
The Reactive C++ Toolbox
Loading...
Searching...
No Matches
Config.ut.cpp
Go to the documentation of this file.
1// The Reactive C++ Toolbox.
2// Copyright (C) 2013-2019 Swirly Cloud Limited
3// Copyright (C) 2022 Reactive Markets Limited
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#include "Config.hpp"
18
19#include <boost/test/unit_test.hpp>
20
21#include <map>
22#include <stdexcept>
23
24using namespace std;
25using namespace toolbox;
26
28
30{
31 const string text{R"(
32# comment
33 # indented comment
34ab
35cd=
36ef=gh
37=ij
38
39kl = mn
40 op = qr
41st = = uv =
42
43)"};
44
45 istringstream is{text};
47 parse_section(is, [&conf](const auto& key, const auto& val) { conf.emplace(key, val); });
48 BOOST_CHECK_EQUAL(conf.size(), 7U);
49 BOOST_CHECK_EQUAL(conf["ab"], "");
50 BOOST_CHECK_EQUAL(conf["cd"], "");
51 BOOST_CHECK_EQUAL(conf["ef"], "gh");
52 BOOST_CHECK_EQUAL(conf[""], "ij");
53 BOOST_CHECK_EQUAL(conf["kl"], "mn");
54 BOOST_CHECK_EQUAL(conf["op"], "qr");
55 BOOST_CHECK_EQUAL(conf["st"], "= uv =");
56 BOOST_CHECK(is.eof());
57}
58
60{
61 const string text{R"(
62# comment
63 # indented comment
64ab
65cd=
66
67[foo]
68ef=gh
69=ij
70
71 [ bar ]
72kl = mn
73 op = qr
74st = = uv =
75
76)"};
77
78 istringstream is{text};
80
81 string next;
83 is, [&conf](const auto& key, const auto& val) { conf.emplace(key, val); }, &next);
84 BOOST_CHECK_EQUAL(conf.size(), 2U);
85 BOOST_CHECK_EQUAL(conf["ab"], "");
86 BOOST_CHECK_EQUAL(conf["cd"], "");
87 BOOST_CHECK_EQUAL(next, "foo");
88 BOOST_CHECK(!is.fail());
89
90 conf.clear();
92 is, [&conf](const auto& key, const auto& val) { conf.emplace(key, val); }, &next);
93 BOOST_CHECK_EQUAL(conf.size(), 2U);
94 BOOST_CHECK_EQUAL(conf["ef"], "gh");
95 BOOST_CHECK_EQUAL(conf[""], "ij");
96 BOOST_CHECK_EQUAL(next, "bar");
97 BOOST_CHECK(!is.fail());
98
99 conf.clear();
101 is, [&conf](const auto& key, const auto& val) { conf.emplace(key, val); }, &next);
103 BOOST_CHECK_EQUAL(conf["kl"], "mn");
104 BOOST_CHECK_EQUAL(conf["op"], "qr");
105 BOOST_CHECK_EQUAL(conf["st"], "= uv =");
106 BOOST_CHECK(next.empty());
107 BOOST_CHECK(is.eof());
108}
109
111{
113
114 BOOST_CHECK_EQUAL(config.get<int>("foo", 101), 101);
115 BOOST_CHECK_EQUAL(config.get<int>("bar", 202), 202);
116
117 config.set("foo", "101");
118 config.set("bar", "202");
119
120 BOOST_CHECK_EQUAL(config.get<int>("foo", 0), 101);
121 BOOST_CHECK_EQUAL(config.get<int>("bar", 0), 202);
122
123 config.set("foo", "303");
124
125 BOOST_CHECK_EQUAL(config.get<int>("foo", 0), 303);
126 BOOST_CHECK_EQUAL(config.get<int>("bar", 0), 202);
127}
128
130{
131 const string text{R"(
132foo=101
133bar=202
134
135[session]
136
137bar=303
138baz=404
139)"};
140
141 istringstream is{text};
142 string next;
143
145 parent.read_section(is, next);
146
147 BOOST_CHECK_EQUAL(parent.size(), 2U);
148 BOOST_CHECK_EQUAL(parent.get<int>("foo", 0), 101);
149 BOOST_CHECK_EQUAL(parent.get<int>("bar", 0), 202);
150 BOOST_CHECK_EQUAL(next, "session");
151 BOOST_CHECK(!is.fail());
153 // Verify that getter with nullptr default compiles.
154 BOOST_CHECK(parent.get("foo", nullptr));
155
156 // Conversion from internal std::string to std::string_view is a special case.
157 BOOST_CHECK_EQUAL(parent.get<string_view>("foo"), "101"sv);
158
160 child.read_section(is, next);
161 child.set_parent(parent);
162
163 BOOST_CHECK_EQUAL(child.size(), 2U);
164 BOOST_CHECK_EQUAL(child.get<int>("foo", 0), 101);
165 BOOST_CHECK_EQUAL(child.get<int>("bar", 0), 303);
166 BOOST_CHECK_EQUAL(child.get<int>("baz", 0), 404);
167 BOOST_CHECK(next.empty());
168 BOOST_CHECK(is.eof());
170 BOOST_CHECK_THROW(child.get("bad"), runtime_error);
171 BOOST_CHECK_THROW(child.get<int>("bad"), runtime_error);
172}
173
175{
176 const string text{R"(
177foo=\a\b\c
178)"};
179
180 istringstream is{text};
181
184
185 BOOST_CHECK_EQUAL(config.size(), 1U);
186 BOOST_CHECK_EQUAL(config.get("foo"), "abc");
187}
188
190{
191 const string text{R"(
192foo = test=++=test
193foo + = test=++=test
194baz1
195baz2=
196baz3 +=
197)"};
198
199 istringstream is{text};
200
204 BOOST_CHECK_EQUAL(config.size(), 5U);
205 BOOST_CHECK_EQUAL(config.get("foo"), "test=++=test");
206 BOOST_CHECK_EQUAL(config.get("foo +"), "test=++=test");
207 BOOST_CHECK_EQUAL(config.get("baz1"), "");
208 BOOST_CHECK_EQUAL(config.get("baz2"), "");
209 BOOST_CHECK_EQUAL(config.get("baz3"), "");
210}
211
213{
214 const string text{R"(
215foo += test=++=test
216foo +==abcd
217)"};
218
219 istringstream is{text};
220
223
225
226 auto rng = config.get_multi("foo");
227 BOOST_CHECK_EQUAL(rng.size(), 2);
228
229 auto it = rng.begin();
230 BOOST_CHECK_EQUAL(*it++, "test=++=test");
231 BOOST_CHECK_EQUAL(*it++, "=abcd");
232 BOOST_CHECK_EQUAL(it == rng.end(), true);
233}
234
236{
237 const string text{R"(
238foo=101
239foo=202
240)"};
241
242 istringstream is{text};
243
246
247 BOOST_CHECK_EQUAL(config.size(), 2U);
248 BOOST_CHECK_EQUAL(config.get("foo"), "202");
249 BOOST_CHECK_EQUAL(config.get<int>("foo"), 202);
250}
251
253{
254 const string text{R"(
255foo+=101
256foo+=202
257)"};
258
259 istringstream is{text};
260
263
264 BOOST_CHECK_EQUAL(config.size(), 2U);
265 BOOST_CHECK_EQUAL(config.get("foo"), "202");
267 auto rng = config.get_multi("foo");
268 BOOST_CHECK_EQUAL(rng.size(), 2);
269
270 auto it = rng.begin();
271 BOOST_CHECK_EQUAL(*it++, "101");
272 BOOST_CHECK_EQUAL(*it++, "202");
273 BOOST_CHECK_EQUAL(it == rng.end(), true);
274}
275
277{
278 const string text{R"(
279foo+=101
280foo+=202
281)"};
282
283 istringstream is{text};
284
287
288 BOOST_CHECK_EQUAL(config.size(), 2U);
289 BOOST_CHECK_EQUAL(config.get<int>("foo"), 202);
290
291 auto rng = config.get_multi<int>("foo");
292 BOOST_CHECK_EQUAL(rng.size(), 2);
293
294 auto it = rng.begin();
295 BOOST_CHECK_EQUAL(*it++, 101);
297 BOOST_CHECK_EQUAL(it == rng.end(), true);
298}
299
301{
302 const string text{R"(
303foo+=101
304foo+=202
305)"};
306
307 istringstream is{text};
308
311
312 BOOST_CHECK_EQUAL(config.size(), 2U);
313 BOOST_CHECK_EQUAL(config.get<string_view>("foo"), "202"sv);
314
315 auto rng = config.get_multi<string_view>("foo");
316 BOOST_CHECK_EQUAL(rng.size(), 2);
317
318 auto it = rng.begin();
319 BOOST_CHECK_EQUAL(*it++, "101"sv);
320 BOOST_CHECK_EQUAL(*it++, "202"sv);
321 BOOST_CHECK_EQUAL(it == rng.end(), true);
322}
323
325{
326 const string text{R"(
327foo=101
328foo=202
329)"};
331 istringstream is{text};
332
334 BOOST_CHECK_NO_THROW(config.read_section(is));
335}
336
338{
339 const string text{R"(
340foo=101
341foo+=202
342)"};
343
344 istringstream is{text};
345
347 BOOST_CHECK_THROW(config.read_section(is), runtime_error);
348}
349
351{
352 const string text{R"(
353foo+=101
354foo=202
355)"};
356
357 istringstream is{text};
360 BOOST_CHECK_THROW(config.read_section(is), runtime_error);
361}
362
364{
365 const string text{R"()"};
366 istringstream is{text};
367
370
371 BOOST_CHECK_EQUAL(config.size(), 0U);
372
373 auto rng = config.get_multi<string_view>("foo");
374 BOOST_CHECK_EQUAL(rng.empty(), true);
375 BOOST_CHECK_EQUAL(rng.size(), 0U);
376 BOOST_CHECK_EQUAL(rng.begin() == rng.end(), true);
377}
378
379
381{
382 const string text{R"(
383foo=101
384)"};
385
386 istringstream is{text};
387
390
391 BOOST_CHECK_EQUAL(config.size(), 1U);
392
393 auto rng = config.get_multi<string_view>("foo");
394 BOOST_CHECK_EQUAL(rng.size(), 1);
395
396 BOOST_CHECK_EQUAL(*rng.begin(), "101"sv);
397}
398
400{
401 const string text{R"(
402foo=101
403)"};
404
405 istringstream is{text};
406
409
410 BOOST_CHECK_EQUAL(config.size(), 1U);
411 BOOST_CHECK_EQUAL(config.get<int>("foo"), 101);
412
413 config.insert("bar", "202");
414 config.insert("foo", "102");
415
416 BOOST_CHECK_EQUAL(config.get("bar"), "202");
417 BOOST_CHECK_EQUAL(config.get<int>("bar"), 202);
418 BOOST_CHECK_EQUAL(config.get<int>("foo"), 102);
419
420 auto foo_rng = config.get_multi<int>("foo");
421 BOOST_CHECK_EQUAL(foo_rng.size(), 2);
422
423 auto foo_it = foo_rng.begin();
424 BOOST_CHECK_EQUAL(*foo_it++, 101);
425 BOOST_CHECK_EQUAL(*foo_it++, 102);
426 BOOST_CHECK_EQUAL(foo_it == foo_rng.end(), true);
427}
428
430{
431 const string text{R"(
432foo=101
433)"};
434
435 istringstream is{text};
436
439
440 BOOST_CHECK_EQUAL(config.size(), 1U);
441 BOOST_CHECK_EQUAL(config.get<int>("foo"), 101);
442
443 config.set("bar", "100");
444 config.set("foo", "111", "222", "333", "444");
445
446 BOOST_CHECK_EQUAL(config.get("bar"), "100");
447 BOOST_CHECK_EQUAL(config.get<int>("bar"), 100);
448 BOOST_CHECK_EQUAL(config.get<int>("foo"), 444);
449
450 auto foo_rng = config.get_multi<int>("foo");
451 BOOST_CHECK_EQUAL(foo_rng.size(), 4);
452
453 auto foo_it = foo_rng.begin();
454 BOOST_CHECK_EQUAL(*foo_it++, 111);
455 BOOST_CHECK_EQUAL(*foo_it++, 222);
456 BOOST_CHECK_EQUAL(*foo_it++, 333);
457 BOOST_CHECK_EQUAL(*foo_it++, 444);
458 BOOST_CHECK_EQUAL(foo_it == foo_rng.end(), true);
459}
460
BOOST_AUTO_TEST_CASE(ParseSectionSingleCase)
Definition Config.ut.cpp:29
BOOST_CHECK_EQUAL(v.size(), 10U)
Simple config reader with environment variable substitution.
Definition Config.hpp:102
std::istream & read_section(std::istream &is)
Definition Config.hpp:166
STL namespace.
std::istream & parse_section(std::istream &is, FnT fn, std::string *name=nullptr)
Definition Config.hpp:33
std::string_view sv
Definition Tokeniser.hpp:26
constexpr auto bind() noexcept
Definition Slot.hpp:92
BOOST_CHECK(isnan(stod(""sv, numeric_limits< double >::quiet_NaN())))