1 /*
2  *          Copyright Andrey Semashev 2007 - 2015.
3  * Distributed under the Boost Software License, Version 1.0.
4  *    (See accompanying file LICENSE_1_0.txt or copy at
5  *          http://www.boost.org/LICENSE_1_0.txt)
6  */
7 /*!
8  * \file   setup_settings_parser.cpp
9  * \author Andrey Semashev
10  * \date   25.08.2013
11  *
12  * \brief  This header contains tests for the settings parser.
13  */
14 
15 #define BOOST_TEST_MODULE setup_settings_parser
16 
17 #include <string>
18 #include <sstream>
19 #include <boost/test/unit_test.hpp>
20 #include <boost/log/utility/setup/settings_parser.hpp>
21 
22 #if !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS)
23 
24 #include <boost/log/exceptions.hpp>
25 
26 namespace logging = boost::log;
27 
28 typedef logging::basic_settings< char > settings;
29 
30 // Tests for single-level settings
BOOST_AUTO_TEST_CASE(single_level)31 BOOST_AUTO_TEST_CASE(single_level)
32 {
33     {
34         std::istringstream strm
35         (
36             "[Section1]\n"
37             "\n"
38             "Param1 = Value1\n"
39             "Param2 = \"hello, \\\"world\\\"\"\n"
40             "\n"
41             "[Section2]\n"
42             "\n"
43             "Param1 = 10\n"
44             "Param2 = -2.2\n"
45         );
46         settings s = logging::parse_settings(strm);
47 
48         BOOST_CHECK(s.has_section("Section1"));
49         BOOST_CHECK(s.has_section("Section2"));
50         BOOST_CHECK(!s.has_section("Section3"));
51 
52         BOOST_CHECK(s.has_parameter("Section1", "Param1"));
53         BOOST_CHECK(s.has_parameter("Section1", "Param2"));
54 
55         BOOST_CHECK(s.has_parameter("Section2", "Param1"));
56         BOOST_CHECK(s.has_parameter("Section2", "Param2"));
57 
58         BOOST_CHECK_EQUAL(s["Section1"]["Param1"].or_default(std::string()), "Value1");
59         BOOST_CHECK_EQUAL(s["Section1"]["Param2"].or_default(std::string()), "hello, \"world\"");
60 
61         BOOST_CHECK_EQUAL(s["Section2"]["Param1"].or_default(std::string()), "10");
62         BOOST_CHECK_EQUAL(s["Section2"]["Param2"].or_default(std::string()), "-2.2");
63     }
64 }
65 
66 // Tests for multi-level settings
BOOST_AUTO_TEST_CASE(multi_level)67 BOOST_AUTO_TEST_CASE(multi_level)
68 {
69     {
70         std::istringstream strm
71         (
72             "  [Section1]\n"
73             "\n"
74             "Param1 = Value1 \n"
75             "Param2=\"hello, \\\"world\\\"\"   \n"
76             "\n"
77             "[Section1.Subsection2]  \n"
78             "\n"
79             "Param1=10\n"
80             "Param2=-2.2\n"
81         );
82         settings s = logging::parse_settings(strm);
83 
84         BOOST_CHECK(s.has_section("Section1"));
85         BOOST_CHECK(s.has_section("Section1.Subsection2"));
86         BOOST_CHECK(!s.has_section("Subsection2"));
87 
88         BOOST_CHECK(s.has_parameter("Section1", "Param1"));
89         BOOST_CHECK(s.has_parameter("Section1", "Param2"));
90 
91         BOOST_CHECK(s.has_parameter("Section1.Subsection2", "Param1"));
92         BOOST_CHECK(s.has_parameter("Section1.Subsection2", "Param2"));
93         BOOST_CHECK(!s.has_parameter("Subsection2", "Param1"));
94         BOOST_CHECK(!s.has_parameter("Subsection2", "Param2"));
95 
96         BOOST_CHECK_EQUAL(s["Section1"]["Param1"].or_default(std::string()), "Value1");
97         BOOST_CHECK_EQUAL(s["Section1"]["Param2"].or_default(std::string()), "hello, \"world\"");
98 
99         BOOST_CHECK_EQUAL(s["Section1.Subsection2"]["Param1"].or_default(std::string()), "10");
100         BOOST_CHECK_EQUAL(s["Section1.Subsection2"]["Param2"].or_default(std::string()), "-2.2");
101     }
102 }
103 
104 // Tests for comments
BOOST_AUTO_TEST_CASE(comments)105 BOOST_AUTO_TEST_CASE(comments)
106 {
107     {
108         std::istringstream strm
109         (
110             "# Some comment\n"
111             "[ Section1 ] # another comment\n"
112             "\n"
113             "Param1 = Value1 ### yet another comment \n"
114             "Param2=\"hello, \\\"world\\\"\" # comment after a quoted string\n"
115             "\n"
116             "[ Section2 ]\n"
117             "\n"
118             "Param1=10#comment after a number\n"
119             "Param2=-2.2#comment without a terminating newline"
120             "\n"
121             "#[Section3]\n"
122             "#\n"
123             "#Param1=10#comment after a number\n"
124             "#Param2=-2.2#comment without a terminating newline"
125         );
126         settings s = logging::parse_settings(strm);
127 
128         BOOST_CHECK(s.has_section("Section1"));
129         BOOST_CHECK(s.has_section("Section2"));
130         BOOST_CHECK(!s.has_section("Section3"));
131 
132         BOOST_CHECK(s.has_parameter("Section1", "Param1"));
133         BOOST_CHECK(s.has_parameter("Section1", "Param2"));
134 
135         BOOST_CHECK(s.has_parameter("Section2", "Param1"));
136         BOOST_CHECK(s.has_parameter("Section2", "Param2"));
137 
138         BOOST_CHECK_EQUAL(s["Section1"]["Param1"].or_default(std::string()), "Value1");
139         BOOST_CHECK_EQUAL(s["Section1"]["Param2"].or_default(std::string()), "hello, \"world\"");
140 
141         BOOST_CHECK_EQUAL(s["Section2"]["Param1"].or_default(std::string()), "10");
142         BOOST_CHECK_EQUAL(s["Section2"]["Param2"].or_default(std::string()), "-2.2");
143     }
144 }
145 
146 // Tests for invalid settings
BOOST_AUTO_TEST_CASE(invalid)147 BOOST_AUTO_TEST_CASE(invalid)
148 {
149     {
150         std::istringstream strm
151         (
152             "Param1 = Value1\n" // parameters outside sections
153             "Param2 = \"hello, \\\"world\\\"\"\n"
154         );
155         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
156     }
157     {
158         std::istringstream strm
159         (
160             "[Section1\n" // missing closing brace
161             "\n"
162             "Param1 = Value1\n"
163             "Param2 = \"hello, \\\"world\\\"\"\n"
164             "\n"
165             "[Section2]\n"
166             "\n"
167             "Param1 = 10\n"
168             "Param2 = -2.2\n"
169         );
170         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
171     }
172     {
173         std::istringstream strm
174         (
175             "Section1]\n" // missing opening brace
176             "\n"
177             "Param1 = Value1\n"
178             "Param2 = \"hello, \\\"world\\\"\"\n"
179             "\n"
180             "[Section2]\n"
181             "\n"
182             "Param1 = 10\n"
183             "Param2 = -2.2\n"
184         );
185         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
186     }
187     {
188         std::istringstream strm
189         (
190             "[Section1=xyz]\n" // invalid characters in the section name
191             "\n"
192             "Param1 = Value1\n"
193             "Param2 = \"hello, \\\"world\\\"\"\n"
194             "\n"
195             "[Section2]\n"
196             "\n"
197             "Param1 = 10\n"
198             "Param2 = -2.2\n"
199         );
200         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
201     }
202     {
203         std::istringstream strm
204         (
205             "[Section1# hello?]\n" // invalid characters in the section name
206             "\n"
207             "Param1 = Value1\n"
208             "Param2 = \"hello, \\\"world\\\"\"\n"
209             "\n"
210             "[Section2]\n"
211             "\n"
212             "Param1 = 10\n"
213             "Param2 = -2.2\n"
214         );
215         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
216     }
217     {
218         std::istringstream strm
219         (
220             "(Section1)\n" // invalid braces
221             "\n"
222             "Param1 = Value1\n"
223             "Param2 = \"hello, \\\"world\\\"\"\n"
224             "\n"
225             "[Section2]\n"
226             "\n"
227             "Param1 = 10\n"
228             "Param2 = -2.2\n"
229         );
230         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
231     }
232     {
233         std::istringstream strm
234         (
235             "[Section1]\n"
236             "\n"
237             "Param1 =\n" // no parameter value
238             "Param2 = \"hello, \\\"world\\\"\"\n"
239             "\n"
240             "[Section2]\n"
241             "\n"
242             "Param1 = 10\n"
243             "Param2 = -2.2\n"
244         );
245         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
246     }
247     {
248         std::istringstream strm
249         (
250             "[Section1]\n"
251             "\n"
252             "Param1\n" // no parameter value
253             "Param2 = \"hello, \\\"world\\\"\"\n"
254             "\n"
255             "[Section2]\n"
256             "\n"
257             "Param1 = 10\n"
258             "Param2 = -2.2\n"
259         );
260         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
261     }
262     {
263         std::istringstream strm
264         (
265             "[Section1]\n"
266             "\n"
267             "Param1 = Value1\n"
268             "Param2 = \"hello, \\\"world\\\"\n" // unterminated quote
269             "\n"
270             "[Section2]\n"
271             "\n"
272             "Param1 = 10\n"
273             "Param2 = -2.2\n"
274         );
275         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
276     }
277     {
278         std::istringstream strm
279         (
280             "[Section1]\n"
281             "\n"
282             "Param1 = Value1 Value2\n" // multi-word value
283             "Param2 = \"hello, \\\"world\\\"\"\n"
284             "\n"
285             "[Section2]\n"
286             "\n"
287             "Param1 = 10\n"
288             "Param2 = -2.2\n"
289         );
290         BOOST_CHECK_THROW(logging::parse_settings(strm), logging::parse_error);
291     }
292 }
293 
294 #endif // !defined(BOOST_LOG_WITHOUT_SETTINGS_PARSERS)
295