1*6b3a42afSjmmv // Copyright 2010 Google Inc.
2*6b3a42afSjmmv // All rights reserved.
3*6b3a42afSjmmv //
4*6b3a42afSjmmv // Redistribution and use in source and binary forms, with or without
5*6b3a42afSjmmv // modification, are permitted provided that the following conditions are
6*6b3a42afSjmmv // met:
7*6b3a42afSjmmv //
8*6b3a42afSjmmv // * Redistributions of source code must retain the above copyright
9*6b3a42afSjmmv // notice, this list of conditions and the following disclaimer.
10*6b3a42afSjmmv // * Redistributions in binary form must reproduce the above copyright
11*6b3a42afSjmmv // notice, this list of conditions and the following disclaimer in the
12*6b3a42afSjmmv // documentation and/or other materials provided with the distribution.
13*6b3a42afSjmmv // * Neither the name of Google Inc. nor the names of its contributors
14*6b3a42afSjmmv // may be used to endorse or promote products derived from this software
15*6b3a42afSjmmv // without specific prior written permission.
16*6b3a42afSjmmv //
17*6b3a42afSjmmv // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*6b3a42afSjmmv // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*6b3a42afSjmmv // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*6b3a42afSjmmv // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*6b3a42afSjmmv // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*6b3a42afSjmmv // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*6b3a42afSjmmv // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*6b3a42afSjmmv // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*6b3a42afSjmmv // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*6b3a42afSjmmv // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*6b3a42afSjmmv // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*6b3a42afSjmmv
29*6b3a42afSjmmv #include "utils/cmdline/base_command.ipp"
30*6b3a42afSjmmv
31*6b3a42afSjmmv #include <atf-c++.hpp>
32*6b3a42afSjmmv
33*6b3a42afSjmmv #include "utils/cmdline/exceptions.hpp"
34*6b3a42afSjmmv #include "utils/cmdline/options.hpp"
35*6b3a42afSjmmv #include "utils/cmdline/parser.ipp"
36*6b3a42afSjmmv #include "utils/cmdline/ui_mock.hpp"
37*6b3a42afSjmmv #include "utils/defs.hpp"
38*6b3a42afSjmmv
39*6b3a42afSjmmv namespace cmdline = utils::cmdline;
40*6b3a42afSjmmv
41*6b3a42afSjmmv
42*6b3a42afSjmmv namespace {
43*6b3a42afSjmmv
44*6b3a42afSjmmv
45*6b3a42afSjmmv /// Mock command to test the cmdline::base_command base class.
46*6b3a42afSjmmv ///
47*6b3a42afSjmmv /// \param Data The type of the opaque data object passed to main().
48*6b3a42afSjmmv /// \param ExpectedData The value run() will expect to find in the Data object
49*6b3a42afSjmmv /// passed to main().
50*6b3a42afSjmmv template< typename Data, Data ExpectedData >
51*6b3a42afSjmmv class mock_cmd : public cmdline::base_command< Data > {
52*6b3a42afSjmmv public:
53*6b3a42afSjmmv /// Indicates if run() has been called already and executed correctly.
54*6b3a42afSjmmv bool executed;
55*6b3a42afSjmmv
56*6b3a42afSjmmv /// Contains the argument of --the_string after run() is executed.
57*6b3a42afSjmmv std::string optvalue;
58*6b3a42afSjmmv
59*6b3a42afSjmmv /// Constructs a new mock command.
mock_cmd(void)60*6b3a42afSjmmv mock_cmd(void) :
61*6b3a42afSjmmv cmdline::base_command< Data >("mock", "arg1 [arg2 [arg3]]", 1, 3,
62*6b3a42afSjmmv "Command for testing."),
63*6b3a42afSjmmv executed(false)
64*6b3a42afSjmmv {
65*6b3a42afSjmmv this->add_option(cmdline::string_option("the_string", "Test option",
66*6b3a42afSjmmv "arg"));
67*6b3a42afSjmmv }
68*6b3a42afSjmmv
69*6b3a42afSjmmv /// Executes the command.
70*6b3a42afSjmmv ///
71*6b3a42afSjmmv /// \param unused_ui Object to interact with the I/O of the program.
72*6b3a42afSjmmv /// \param cmdline Representation of the command line to the subcommand.
73*6b3a42afSjmmv /// \param data Arbitrary data cookie passed to the command.
74*6b3a42afSjmmv ///
75*6b3a42afSjmmv /// \return A hardcoded number for testing purposes.
76*6b3a42afSjmmv int
run(cmdline::ui * UTILS_UNUSED_PARAM (ui),const cmdline::parsed_cmdline & cmdline,const Data & data)77*6b3a42afSjmmv run(cmdline::ui* UTILS_UNUSED_PARAM(ui),
78*6b3a42afSjmmv const cmdline::parsed_cmdline& cmdline, const Data& data)
79*6b3a42afSjmmv {
80*6b3a42afSjmmv if (cmdline.has_option("the_string"))
81*6b3a42afSjmmv optvalue = cmdline.get_option< cmdline::string_option >(
82*6b3a42afSjmmv "the_string");
83*6b3a42afSjmmv ATF_REQUIRE_EQ(ExpectedData, data);
84*6b3a42afSjmmv executed = true;
85*6b3a42afSjmmv return 1234;
86*6b3a42afSjmmv }
87*6b3a42afSjmmv };
88*6b3a42afSjmmv
89*6b3a42afSjmmv
90*6b3a42afSjmmv /// Mock command to test the cmdline::base_command_no_data base class.
91*6b3a42afSjmmv class mock_cmd_no_data : public cmdline::base_command_no_data {
92*6b3a42afSjmmv public:
93*6b3a42afSjmmv /// Indicates if run() has been called already and executed correctly.
94*6b3a42afSjmmv bool executed;
95*6b3a42afSjmmv
96*6b3a42afSjmmv /// Contains the argument of --the_string after run() is executed.
97*6b3a42afSjmmv std::string optvalue;
98*6b3a42afSjmmv
99*6b3a42afSjmmv /// Constructs a new mock command.
mock_cmd_no_data(void)100*6b3a42afSjmmv mock_cmd_no_data(void) :
101*6b3a42afSjmmv cmdline::base_command_no_data("mock", "arg1 [arg2 [arg3]]", 1, 3,
102*6b3a42afSjmmv "Command for testing."),
103*6b3a42afSjmmv executed(false)
104*6b3a42afSjmmv {
105*6b3a42afSjmmv add_option(cmdline::string_option("the_string", "Test option", "arg"));
106*6b3a42afSjmmv }
107*6b3a42afSjmmv
108*6b3a42afSjmmv /// Executes the command.
109*6b3a42afSjmmv ///
110*6b3a42afSjmmv /// \param unused_ui Object to interact with the I/O of the program.
111*6b3a42afSjmmv /// \param cmdline Representation of the command line to the subcommand.
112*6b3a42afSjmmv ///
113*6b3a42afSjmmv /// \return A hardcoded number for testing purposes.
114*6b3a42afSjmmv int
run(cmdline::ui * UTILS_UNUSED_PARAM (ui),const cmdline::parsed_cmdline & cmdline)115*6b3a42afSjmmv run(cmdline::ui* UTILS_UNUSED_PARAM(ui),
116*6b3a42afSjmmv const cmdline::parsed_cmdline& cmdline)
117*6b3a42afSjmmv {
118*6b3a42afSjmmv if (cmdline.has_option("the_string"))
119*6b3a42afSjmmv optvalue = cmdline.get_option< cmdline::string_option >(
120*6b3a42afSjmmv "the_string");
121*6b3a42afSjmmv executed = true;
122*6b3a42afSjmmv return 1234;
123*6b3a42afSjmmv }
124*6b3a42afSjmmv };
125*6b3a42afSjmmv
126*6b3a42afSjmmv
127*6b3a42afSjmmv /// Implementation of a command to get access to parse_cmdline().
128*6b3a42afSjmmv class parse_cmdline_portal : public cmdline::command_proto {
129*6b3a42afSjmmv public:
130*6b3a42afSjmmv /// Constructs a new mock command.
parse_cmdline_portal(void)131*6b3a42afSjmmv parse_cmdline_portal(void) :
132*6b3a42afSjmmv cmdline::command_proto("portal", "arg1 [arg2 [arg3]]", 1, 3,
133*6b3a42afSjmmv "Command for testing.")
134*6b3a42afSjmmv {
135*6b3a42afSjmmv this->add_option(cmdline::string_option("the_string", "Test option",
136*6b3a42afSjmmv "arg"));
137*6b3a42afSjmmv }
138*6b3a42afSjmmv
139*6b3a42afSjmmv /// Delegator for the internal parse_cmdline() method.
140*6b3a42afSjmmv ///
141*6b3a42afSjmmv /// \param args The input arguments to be parsed.
142*6b3a42afSjmmv ///
143*6b3a42afSjmmv /// \return The parsed command line, split in options and arguments.
144*6b3a42afSjmmv cmdline::parsed_cmdline
operator ()(const cmdline::args_vector & args) const145*6b3a42afSjmmv operator()(const cmdline::args_vector& args) const
146*6b3a42afSjmmv {
147*6b3a42afSjmmv return parse_cmdline(args);
148*6b3a42afSjmmv }
149*6b3a42afSjmmv };
150*6b3a42afSjmmv
151*6b3a42afSjmmv
152*6b3a42afSjmmv } // anonymous namespace
153*6b3a42afSjmmv
154*6b3a42afSjmmv
155*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__ok);
ATF_TEST_CASE_BODY(command_proto__parse_cmdline__ok)156*6b3a42afSjmmv ATF_TEST_CASE_BODY(command_proto__parse_cmdline__ok)
157*6b3a42afSjmmv {
158*6b3a42afSjmmv cmdline::args_vector args;
159*6b3a42afSjmmv args.push_back("portal");
160*6b3a42afSjmmv args.push_back("--the_string=foo bar");
161*6b3a42afSjmmv args.push_back("one arg");
162*6b3a42afSjmmv args.push_back("another arg");
163*6b3a42afSjmmv (void)parse_cmdline_portal()(args);
164*6b3a42afSjmmv }
165*6b3a42afSjmmv
166*6b3a42afSjmmv
167*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__parse_fail);
ATF_TEST_CASE_BODY(command_proto__parse_cmdline__parse_fail)168*6b3a42afSjmmv ATF_TEST_CASE_BODY(command_proto__parse_cmdline__parse_fail)
169*6b3a42afSjmmv {
170*6b3a42afSjmmv cmdline::args_vector args;
171*6b3a42afSjmmv args.push_back("portal");
172*6b3a42afSjmmv args.push_back("--foo-bar");
173*6b3a42afSjmmv ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar",
174*6b3a42afSjmmv (void)parse_cmdline_portal()(args));
175*6b3a42afSjmmv }
176*6b3a42afSjmmv
177*6b3a42afSjmmv
178*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__args_invalid);
ATF_TEST_CASE_BODY(command_proto__parse_cmdline__args_invalid)179*6b3a42afSjmmv ATF_TEST_CASE_BODY(command_proto__parse_cmdline__args_invalid)
180*6b3a42afSjmmv {
181*6b3a42afSjmmv cmdline::args_vector args;
182*6b3a42afSjmmv args.push_back("portal");
183*6b3a42afSjmmv
184*6b3a42afSjmmv ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Not enough arguments",
185*6b3a42afSjmmv (void)parse_cmdline_portal()(args));
186*6b3a42afSjmmv
187*6b3a42afSjmmv args.push_back("1");
188*6b3a42afSjmmv args.push_back("2");
189*6b3a42afSjmmv args.push_back("3");
190*6b3a42afSjmmv args.push_back("4");
191*6b3a42afSjmmv ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Too many arguments",
192*6b3a42afSjmmv (void)parse_cmdline_portal()(args));
193*6b3a42afSjmmv }
194*6b3a42afSjmmv
195*6b3a42afSjmmv
196*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(base_command__getters);
ATF_TEST_CASE_BODY(base_command__getters)197*6b3a42afSjmmv ATF_TEST_CASE_BODY(base_command__getters)
198*6b3a42afSjmmv {
199*6b3a42afSjmmv mock_cmd< int, 584 > cmd;
200*6b3a42afSjmmv ATF_REQUIRE_EQ("mock", cmd.name());
201*6b3a42afSjmmv ATF_REQUIRE_EQ("arg1 [arg2 [arg3]]", cmd.arg_list());
202*6b3a42afSjmmv ATF_REQUIRE_EQ("Command for testing.", cmd.short_description());
203*6b3a42afSjmmv ATF_REQUIRE_EQ(1, cmd.options().size());
204*6b3a42afSjmmv ATF_REQUIRE_EQ("the_string", cmd.options()[0]->long_name());
205*6b3a42afSjmmv }
206*6b3a42afSjmmv
207*6b3a42afSjmmv
208*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(base_command__main__ok)
ATF_TEST_CASE_BODY(base_command__main__ok)209*6b3a42afSjmmv ATF_TEST_CASE_BODY(base_command__main__ok)
210*6b3a42afSjmmv {
211*6b3a42afSjmmv mock_cmd< int, 584 > cmd;
212*6b3a42afSjmmv
213*6b3a42afSjmmv cmdline::ui_mock ui;
214*6b3a42afSjmmv cmdline::args_vector args;
215*6b3a42afSjmmv args.push_back("mock");
216*6b3a42afSjmmv args.push_back("--the_string=foo bar");
217*6b3a42afSjmmv args.push_back("one arg");
218*6b3a42afSjmmv args.push_back("another arg");
219*6b3a42afSjmmv ATF_REQUIRE_EQ(1234, cmd.main(&ui, args, 584));
220*6b3a42afSjmmv ATF_REQUIRE(cmd.executed);
221*6b3a42afSjmmv ATF_REQUIRE_EQ("foo bar", cmd.optvalue);
222*6b3a42afSjmmv }
223*6b3a42afSjmmv
224*6b3a42afSjmmv
225*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(base_command__main__parse_cmdline_fail)
ATF_TEST_CASE_BODY(base_command__main__parse_cmdline_fail)226*6b3a42afSjmmv ATF_TEST_CASE_BODY(base_command__main__parse_cmdline_fail)
227*6b3a42afSjmmv {
228*6b3a42afSjmmv mock_cmd< int, 584 > cmd;
229*6b3a42afSjmmv
230*6b3a42afSjmmv cmdline::ui_mock ui;
231*6b3a42afSjmmv cmdline::args_vector args;
232*6b3a42afSjmmv args.push_back("mock");
233*6b3a42afSjmmv args.push_back("--foo-bar");
234*6b3a42afSjmmv ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar",
235*6b3a42afSjmmv cmd.main(&ui, args, 584));
236*6b3a42afSjmmv ATF_REQUIRE(!cmd.executed);
237*6b3a42afSjmmv }
238*6b3a42afSjmmv
239*6b3a42afSjmmv
240*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__getters);
ATF_TEST_CASE_BODY(base_command_no_data__getters)241*6b3a42afSjmmv ATF_TEST_CASE_BODY(base_command_no_data__getters)
242*6b3a42afSjmmv {
243*6b3a42afSjmmv mock_cmd_no_data cmd;
244*6b3a42afSjmmv ATF_REQUIRE_EQ("mock", cmd.name());
245*6b3a42afSjmmv ATF_REQUIRE_EQ("arg1 [arg2 [arg3]]", cmd.arg_list());
246*6b3a42afSjmmv ATF_REQUIRE_EQ("Command for testing.", cmd.short_description());
247*6b3a42afSjmmv ATF_REQUIRE_EQ(1, cmd.options().size());
248*6b3a42afSjmmv ATF_REQUIRE_EQ("the_string", cmd.options()[0]->long_name());
249*6b3a42afSjmmv }
250*6b3a42afSjmmv
251*6b3a42afSjmmv
252*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__main__ok)
ATF_TEST_CASE_BODY(base_command_no_data__main__ok)253*6b3a42afSjmmv ATF_TEST_CASE_BODY(base_command_no_data__main__ok)
254*6b3a42afSjmmv {
255*6b3a42afSjmmv mock_cmd_no_data cmd;
256*6b3a42afSjmmv
257*6b3a42afSjmmv cmdline::ui_mock ui;
258*6b3a42afSjmmv cmdline::args_vector args;
259*6b3a42afSjmmv args.push_back("mock");
260*6b3a42afSjmmv args.push_back("--the_string=foo bar");
261*6b3a42afSjmmv args.push_back("one arg");
262*6b3a42afSjmmv args.push_back("another arg");
263*6b3a42afSjmmv ATF_REQUIRE_EQ(1234, cmd.main(&ui, args));
264*6b3a42afSjmmv ATF_REQUIRE(cmd.executed);
265*6b3a42afSjmmv ATF_REQUIRE_EQ("foo bar", cmd.optvalue);
266*6b3a42afSjmmv }
267*6b3a42afSjmmv
268*6b3a42afSjmmv
269*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__main__parse_cmdline_fail)
ATF_TEST_CASE_BODY(base_command_no_data__main__parse_cmdline_fail)270*6b3a42afSjmmv ATF_TEST_CASE_BODY(base_command_no_data__main__parse_cmdline_fail)
271*6b3a42afSjmmv {
272*6b3a42afSjmmv mock_cmd_no_data cmd;
273*6b3a42afSjmmv
274*6b3a42afSjmmv cmdline::ui_mock ui;
275*6b3a42afSjmmv cmdline::args_vector args;
276*6b3a42afSjmmv args.push_back("mock");
277*6b3a42afSjmmv args.push_back("--foo-bar");
278*6b3a42afSjmmv ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar",
279*6b3a42afSjmmv cmd.main(&ui, args));
280*6b3a42afSjmmv ATF_REQUIRE(!cmd.executed);
281*6b3a42afSjmmv }
282*6b3a42afSjmmv
283*6b3a42afSjmmv
ATF_INIT_TEST_CASES(tcs)284*6b3a42afSjmmv ATF_INIT_TEST_CASES(tcs)
285*6b3a42afSjmmv {
286*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__ok);
287*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__parse_fail);
288*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__args_invalid);
289*6b3a42afSjmmv
290*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, base_command__getters);
291*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, base_command__main__ok);
292*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, base_command__main__parse_cmdline_fail);
293*6b3a42afSjmmv
294*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, base_command_no_data__getters);
295*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, base_command_no_data__main__ok);
296*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, base_command_no_data__main__parse_cmdline_fail);
297*6b3a42afSjmmv }
298