Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/kyua/utils/config/parser_test.cpp
48081 views
1
// Copyright 2012 The Kyua Authors.
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
6
// met:
7
//
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above copyright
11
// notice, this list of conditions and the following disclaimer in the
12
// documentation and/or other materials provided with the distribution.
13
// * Neither the name of Google Inc. nor the names of its contributors
14
// may be used to endorse or promote products derived from this software
15
// without specific prior written permission.
16
//
17
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
#include "utils/config/parser.hpp"
30
31
#include <stdexcept>
32
33
#include <atf-c++.hpp>
34
35
#include "utils/config/exceptions.hpp"
36
#include "utils/config/parser.hpp"
37
#include "utils/config/tree.ipp"
38
#include "utils/format/macros.hpp"
39
#include "utils/fs/path.hpp"
40
41
namespace config = utils::config;
42
namespace fs = utils::fs;
43
44
45
namespace {
46
47
48
/// Implementation of a parser for testing purposes.
49
class mock_parser : public config::parser {
50
/// Initializes the tree keys before reading the file.
51
///
52
/// \param [in,out] tree The tree in which to define the key structure.
53
/// \param syntax_version The version of the file format as specified in the
54
/// configuration file.
55
void
56
setup(config::tree& tree, const int syntax_version)
57
{
58
if (syntax_version == 1) {
59
// Do nothing on config_tree.
60
} else if (syntax_version == 2) {
61
tree.define< config::string_node >("top_string");
62
tree.define< config::int_node >("inner.int");
63
tree.define_dynamic("inner.dynamic");
64
} else {
65
throw std::runtime_error(F("Unknown syntax version %s") %
66
syntax_version);
67
}
68
}
69
70
public:
71
/// Initializes a parser.
72
///
73
/// \param tree The mock config tree to parse.
74
mock_parser(config::tree& tree) :
75
config::parser(tree)
76
{
77
}
78
};
79
80
81
} // anonymous namespace
82
83
84
ATF_TEST_CASE_WITHOUT_HEAD(no_keys__ok);
85
ATF_TEST_CASE_BODY(no_keys__ok)
86
{
87
atf::utils::create_file(
88
"output.lua",
89
"syntax(2)\n"
90
"local foo = 'value'\n");
91
92
config::tree tree;
93
mock_parser(tree).parse(fs::path("output.lua"));
94
ATF_REQUIRE_THROW(config::unknown_key_error,
95
tree.lookup< config::string_node >("foo"));
96
}
97
98
99
ATF_TEST_CASE_WITHOUT_HEAD(no_keys__unknown_key);
100
ATF_TEST_CASE_BODY(no_keys__unknown_key)
101
{
102
atf::utils::create_file(
103
"output.lua",
104
"syntax(2)\n"
105
"foo = 'value'\n");
106
107
config::tree tree;
108
ATF_REQUIRE_THROW_RE(config::syntax_error, "foo",
109
mock_parser(tree).parse(fs::path("output.lua")));
110
}
111
112
113
ATF_TEST_CASE_WITHOUT_HEAD(some_keys__ok);
114
ATF_TEST_CASE_BODY(some_keys__ok)
115
{
116
atf::utils::create_file(
117
"output.lua",
118
"syntax(2)\n"
119
"top_string = 'foo'\n"
120
"inner.int = 12345\n"
121
"inner.dynamic.foo = 78\n"
122
"inner.dynamic.bar = 'some text'\n");
123
124
config::tree tree;
125
mock_parser(tree).parse(fs::path("output.lua"));
126
ATF_REQUIRE_EQ("foo", tree.lookup< config::string_node >("top_string"));
127
ATF_REQUIRE_EQ(12345, tree.lookup< config::int_node >("inner.int"));
128
ATF_REQUIRE_EQ("78",
129
tree.lookup< config::string_node >("inner.dynamic.foo"));
130
ATF_REQUIRE_EQ("some text",
131
tree.lookup< config::string_node >("inner.dynamic.bar"));
132
}
133
134
135
ATF_TEST_CASE_WITHOUT_HEAD(some_keys__not_strict);
136
ATF_TEST_CASE_BODY(some_keys__not_strict)
137
{
138
atf::utils::create_file(
139
"output.lua",
140
"syntax(2)\n"
141
"top_string = 'foo'\n"
142
"unknown_string = 'bar'\n"
143
"top_string = 'baz'\n");
144
145
config::tree tree(false);
146
mock_parser(tree).parse(fs::path("output.lua"));
147
ATF_REQUIRE_EQ("baz", tree.lookup< config::string_node >("top_string"));
148
ATF_REQUIRE(!tree.is_set("unknown_string"));
149
}
150
151
152
ATF_TEST_CASE_WITHOUT_HEAD(some_keys__unknown_key);
153
ATF_TEST_CASE_BODY(some_keys__unknown_key)
154
{
155
atf::utils::create_file(
156
"output.lua",
157
"syntax(2)\n"
158
"top_string2 = 'foo'\n");
159
config::tree tree1;
160
ATF_REQUIRE_THROW_RE(config::syntax_error,
161
"Unknown configuration property 'top_string2'",
162
mock_parser(tree1).parse(fs::path("output.lua")));
163
164
atf::utils::create_file(
165
"output.lua",
166
"syntax(2)\n"
167
"inner.int2 = 12345\n");
168
config::tree tree2;
169
ATF_REQUIRE_THROW_RE(config::syntax_error,
170
"Unknown configuration property 'inner.int2'",
171
mock_parser(tree2).parse(fs::path("output.lua")));
172
}
173
174
175
ATF_TEST_CASE_WITHOUT_HEAD(invalid_syntax);
176
ATF_TEST_CASE_BODY(invalid_syntax)
177
{
178
config::tree tree;
179
180
atf::utils::create_file("output.lua", "syntax(56)\n");
181
ATF_REQUIRE_THROW_RE(config::syntax_error,
182
"Unknown syntax version 56",
183
mock_parser(tree).parse(fs::path("output.lua")));
184
}
185
186
187
ATF_TEST_CASE_WITHOUT_HEAD(syntax_deprecated_format);
188
ATF_TEST_CASE_BODY(syntax_deprecated_format)
189
{
190
config::tree tree;
191
192
atf::utils::create_file("output.lua", "syntax('config', 1)\n");
193
(void)mock_parser(tree).parse(fs::path("output.lua"));
194
195
atf::utils::create_file("output.lua", "syntax('foo', 1)\n");
196
ATF_REQUIRE_THROW_RE(config::syntax_error, "must be 'config'",
197
mock_parser(tree).parse(fs::path("output.lua")));
198
199
atf::utils::create_file("output.lua", "syntax('config', 2)\n");
200
ATF_REQUIRE_THROW_RE(config::syntax_error, "only takes one argument",
201
mock_parser(tree).parse(fs::path("output.lua")));
202
}
203
204
205
ATF_TEST_CASE_WITHOUT_HEAD(syntax_not_called);
206
ATF_TEST_CASE_BODY(syntax_not_called)
207
{
208
config::tree tree;
209
tree.define< config::int_node >("var");
210
211
atf::utils::create_file("output.lua", "var = 3\n");
212
ATF_REQUIRE_THROW_RE(config::syntax_error, "No syntax defined",
213
mock_parser(tree).parse(fs::path("output.lua")));
214
215
ATF_REQUIRE(!tree.is_set("var"));
216
}
217
218
219
ATF_TEST_CASE_WITHOUT_HEAD(syntax_called_more_than_once);
220
ATF_TEST_CASE_BODY(syntax_called_more_than_once)
221
{
222
config::tree tree;
223
tree.define< config::int_node >("var");
224
225
atf::utils::create_file(
226
"output.lua",
227
"syntax(2)\n"
228
"var = 3\n"
229
"syntax(2)\n"
230
"var = 5\n");
231
ATF_REQUIRE_THROW_RE(config::syntax_error,
232
"syntax\\(\\) can only be called once",
233
mock_parser(tree).parse(fs::path("output.lua")));
234
235
ATF_REQUIRE_EQ(3, tree.lookup< config::int_node >("var"));
236
}
237
238
239
ATF_INIT_TEST_CASES(tcs)
240
{
241
ATF_ADD_TEST_CASE(tcs, no_keys__ok);
242
ATF_ADD_TEST_CASE(tcs, no_keys__unknown_key);
243
244
ATF_ADD_TEST_CASE(tcs, some_keys__ok);
245
ATF_ADD_TEST_CASE(tcs, some_keys__not_strict);
246
ATF_ADD_TEST_CASE(tcs, some_keys__unknown_key);
247
248
ATF_ADD_TEST_CASE(tcs, invalid_syntax);
249
ATF_ADD_TEST_CASE(tcs, syntax_deprecated_format);
250
ATF_ADD_TEST_CASE(tcs, syntax_not_called);
251
ATF_ADD_TEST_CASE(tcs, syntax_called_more_than_once);
252
}
253
254