Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/kyua/utils/cmdline/base_command_test.cpp
48178 views
1
// Copyright 2010 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/cmdline/base_command.ipp"
30
31
#include <atf-c++.hpp>
32
33
#include "utils/cmdline/exceptions.hpp"
34
#include "utils/cmdline/options.hpp"
35
#include "utils/cmdline/parser.ipp"
36
#include "utils/cmdline/ui_mock.hpp"
37
#include "utils/defs.hpp"
38
39
namespace cmdline = utils::cmdline;
40
41
42
namespace {
43
44
45
/// Mock command to test the cmdline::base_command base class.
46
///
47
/// \param Data The type of the opaque data object passed to main().
48
/// \param ExpectedData The value run() will expect to find in the Data object
49
/// passed to main().
50
template< typename Data, Data ExpectedData >
51
class mock_cmd : public cmdline::base_command< Data > {
52
public:
53
/// Indicates if run() has been called already and executed correctly.
54
bool executed;
55
56
/// Contains the argument of --the_string after run() is executed.
57
std::string optvalue;
58
59
/// Constructs a new mock command.
60
mock_cmd(void) :
61
cmdline::base_command< Data >("mock", "arg1 [arg2 [arg3]]", 1, 3,
62
"Command for testing."),
63
executed(false)
64
{
65
this->add_option(cmdline::string_option("the_string", "Test option",
66
"arg"));
67
}
68
69
/// Executes the command.
70
///
71
/// \param cmdline Representation of the command line to the subcommand.
72
/// \param data Arbitrary data cookie passed to the command.
73
///
74
/// \return A hardcoded number for testing purposes.
75
int
76
run(cmdline::ui* /* ui */,
77
const cmdline::parsed_cmdline& cmdline, const Data& data)
78
{
79
if (cmdline.has_option("the_string"))
80
optvalue = cmdline.get_option< cmdline::string_option >(
81
"the_string");
82
ATF_REQUIRE_EQ(ExpectedData, data);
83
executed = true;
84
return 1234;
85
}
86
};
87
88
89
/// Mock command to test the cmdline::base_command_no_data base class.
90
class mock_cmd_no_data : public cmdline::base_command_no_data {
91
public:
92
/// Indicates if run() has been called already and executed correctly.
93
bool executed;
94
95
/// Contains the argument of --the_string after run() is executed.
96
std::string optvalue;
97
98
/// Constructs a new mock command.
99
mock_cmd_no_data(void) :
100
cmdline::base_command_no_data("mock", "arg1 [arg2 [arg3]]", 1, 3,
101
"Command for testing."),
102
executed(false)
103
{
104
add_option(cmdline::string_option("the_string", "Test option", "arg"));
105
}
106
107
/// Executes the command.
108
///
109
/// \param cmdline Representation of the command line to the subcommand.
110
///
111
/// \return A hardcoded number for testing purposes.
112
int
113
run(cmdline::ui* /* ui */,
114
const cmdline::parsed_cmdline& cmdline)
115
{
116
if (cmdline.has_option("the_string"))
117
optvalue = cmdline.get_option< cmdline::string_option >(
118
"the_string");
119
executed = true;
120
return 1234;
121
}
122
};
123
124
125
/// Implementation of a command to get access to parse_cmdline().
126
class parse_cmdline_portal : public cmdline::command_proto {
127
public:
128
/// Constructs a new mock command.
129
parse_cmdline_portal(void) :
130
cmdline::command_proto("portal", "arg1 [arg2 [arg3]]", 1, 3,
131
"Command for testing.")
132
{
133
this->add_option(cmdline::string_option("the_string", "Test option",
134
"arg"));
135
}
136
137
/// Delegator for the internal parse_cmdline() method.
138
///
139
/// \param args The input arguments to be parsed.
140
///
141
/// \return The parsed command line, split in options and arguments.
142
cmdline::parsed_cmdline
143
operator()(const cmdline::args_vector& args) const
144
{
145
return parse_cmdline(args);
146
}
147
};
148
149
150
} // anonymous namespace
151
152
153
ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__ok);
154
ATF_TEST_CASE_BODY(command_proto__parse_cmdline__ok)
155
{
156
cmdline::args_vector args;
157
args.push_back("portal");
158
args.push_back("--the_string=foo bar");
159
args.push_back("one arg");
160
args.push_back("another arg");
161
(void)parse_cmdline_portal()(args);
162
}
163
164
165
ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__parse_fail);
166
ATF_TEST_CASE_BODY(command_proto__parse_cmdline__parse_fail)
167
{
168
cmdline::args_vector args;
169
args.push_back("portal");
170
args.push_back("--foo-bar");
171
ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar",
172
(void)parse_cmdline_portal()(args));
173
}
174
175
176
ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__args_invalid);
177
ATF_TEST_CASE_BODY(command_proto__parse_cmdline__args_invalid)
178
{
179
cmdline::args_vector args;
180
args.push_back("portal");
181
182
ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Not enough arguments",
183
(void)parse_cmdline_portal()(args));
184
185
args.push_back("1");
186
args.push_back("2");
187
args.push_back("3");
188
args.push_back("4");
189
ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Too many arguments",
190
(void)parse_cmdline_portal()(args));
191
}
192
193
194
ATF_TEST_CASE_WITHOUT_HEAD(base_command__getters);
195
ATF_TEST_CASE_BODY(base_command__getters)
196
{
197
mock_cmd< int, 584 > cmd;
198
ATF_REQUIRE_EQ("mock", cmd.name());
199
ATF_REQUIRE_EQ("arg1 [arg2 [arg3]]", cmd.arg_list());
200
ATF_REQUIRE_EQ("Command for testing.", cmd.short_description());
201
ATF_REQUIRE_EQ(1, cmd.options().size());
202
ATF_REQUIRE_EQ("the_string", cmd.options()[0]->long_name());
203
}
204
205
206
ATF_TEST_CASE_WITHOUT_HEAD(base_command__main__ok)
207
ATF_TEST_CASE_BODY(base_command__main__ok)
208
{
209
mock_cmd< int, 584 > cmd;
210
211
cmdline::ui_mock ui;
212
cmdline::args_vector args;
213
args.push_back("mock");
214
args.push_back("--the_string=foo bar");
215
args.push_back("one arg");
216
args.push_back("another arg");
217
ATF_REQUIRE_EQ(1234, cmd.main(&ui, args, 584));
218
ATF_REQUIRE(cmd.executed);
219
ATF_REQUIRE_EQ("foo bar", cmd.optvalue);
220
}
221
222
223
ATF_TEST_CASE_WITHOUT_HEAD(base_command__main__parse_cmdline_fail)
224
ATF_TEST_CASE_BODY(base_command__main__parse_cmdline_fail)
225
{
226
mock_cmd< int, 584 > cmd;
227
228
cmdline::ui_mock ui;
229
cmdline::args_vector args;
230
args.push_back("mock");
231
args.push_back("--foo-bar");
232
ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar",
233
cmd.main(&ui, args, 584));
234
ATF_REQUIRE(!cmd.executed);
235
}
236
237
238
ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__getters);
239
ATF_TEST_CASE_BODY(base_command_no_data__getters)
240
{
241
mock_cmd_no_data cmd;
242
ATF_REQUIRE_EQ("mock", cmd.name());
243
ATF_REQUIRE_EQ("arg1 [arg2 [arg3]]", cmd.arg_list());
244
ATF_REQUIRE_EQ("Command for testing.", cmd.short_description());
245
ATF_REQUIRE_EQ(1, cmd.options().size());
246
ATF_REQUIRE_EQ("the_string", cmd.options()[0]->long_name());
247
}
248
249
250
ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__main__ok)
251
ATF_TEST_CASE_BODY(base_command_no_data__main__ok)
252
{
253
mock_cmd_no_data cmd;
254
255
cmdline::ui_mock ui;
256
cmdline::args_vector args;
257
args.push_back("mock");
258
args.push_back("--the_string=foo bar");
259
args.push_back("one arg");
260
args.push_back("another arg");
261
ATF_REQUIRE_EQ(1234, cmd.main(&ui, args));
262
ATF_REQUIRE(cmd.executed);
263
ATF_REQUIRE_EQ("foo bar", cmd.optvalue);
264
}
265
266
267
ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__main__parse_cmdline_fail)
268
ATF_TEST_CASE_BODY(base_command_no_data__main__parse_cmdline_fail)
269
{
270
mock_cmd_no_data cmd;
271
272
cmdline::ui_mock ui;
273
cmdline::args_vector args;
274
args.push_back("mock");
275
args.push_back("--foo-bar");
276
ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar",
277
cmd.main(&ui, args));
278
ATF_REQUIRE(!cmd.executed);
279
}
280
281
282
ATF_INIT_TEST_CASES(tcs)
283
{
284
ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__ok);
285
ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__parse_fail);
286
ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__args_invalid);
287
288
ATF_ADD_TEST_CASE(tcs, base_command__getters);
289
ATF_ADD_TEST_CASE(tcs, base_command__main__ok);
290
ATF_ADD_TEST_CASE(tcs, base_command__main__parse_cmdline_fail);
291
292
ATF_ADD_TEST_CASE(tcs, base_command_no_data__getters);
293
ATF_ADD_TEST_CASE(tcs, base_command_no_data__main__ok);
294
ATF_ADD_TEST_CASE(tcs, base_command_no_data__main__parse_cmdline_fail);
295
}
296
297