xref: /src/contrib/kyua/utils/cmdline/base_command_test.cpp (revision b0d29bc47dba79f6f38e67eabadfb4b32ffd9390)
108334c51SBrooks Davis // Copyright 2010 The Kyua Authors.
208334c51SBrooks Davis // All rights reserved.
308334c51SBrooks Davis //
408334c51SBrooks Davis // Redistribution and use in source and binary forms, with or without
508334c51SBrooks Davis // modification, are permitted provided that the following conditions are
608334c51SBrooks Davis // met:
708334c51SBrooks Davis //
808334c51SBrooks Davis // * Redistributions of source code must retain the above copyright
908334c51SBrooks Davis //   notice, this list of conditions and the following disclaimer.
1008334c51SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
1108334c51SBrooks Davis //   notice, this list of conditions and the following disclaimer in the
1208334c51SBrooks Davis //   documentation and/or other materials provided with the distribution.
1308334c51SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
1408334c51SBrooks Davis //   may be used to endorse or promote products derived from this software
1508334c51SBrooks Davis //   without specific prior written permission.
1608334c51SBrooks Davis //
1708334c51SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1808334c51SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1908334c51SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2008334c51SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2108334c51SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2208334c51SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2308334c51SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2408334c51SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2508334c51SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2608334c51SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2708334c51SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2808334c51SBrooks Davis 
2908334c51SBrooks Davis #include "utils/cmdline/base_command.ipp"
3008334c51SBrooks Davis 
3108334c51SBrooks Davis #include <atf-c++.hpp>
3208334c51SBrooks Davis 
3308334c51SBrooks Davis #include "utils/cmdline/exceptions.hpp"
3408334c51SBrooks Davis #include "utils/cmdline/options.hpp"
3508334c51SBrooks Davis #include "utils/cmdline/parser.ipp"
3608334c51SBrooks Davis #include "utils/cmdline/ui_mock.hpp"
3708334c51SBrooks Davis #include "utils/defs.hpp"
3808334c51SBrooks Davis 
3908334c51SBrooks Davis namespace cmdline = utils::cmdline;
4008334c51SBrooks Davis 
4108334c51SBrooks Davis 
4208334c51SBrooks Davis namespace {
4308334c51SBrooks Davis 
4408334c51SBrooks Davis 
4508334c51SBrooks Davis /// Mock command to test the cmdline::base_command base class.
4608334c51SBrooks Davis ///
4708334c51SBrooks Davis /// \param Data The type of the opaque data object passed to main().
4808334c51SBrooks Davis /// \param ExpectedData The value run() will expect to find in the Data object
4908334c51SBrooks Davis ///     passed to main().
5008334c51SBrooks Davis template< typename Data, Data ExpectedData >
5108334c51SBrooks Davis class mock_cmd : public cmdline::base_command< Data > {
5208334c51SBrooks Davis public:
5308334c51SBrooks Davis     /// Indicates if run() has been called already and executed correctly.
5408334c51SBrooks Davis     bool executed;
5508334c51SBrooks Davis 
5608334c51SBrooks Davis     /// Contains the argument of --the_string after run() is executed.
5708334c51SBrooks Davis     std::string optvalue;
5808334c51SBrooks Davis 
5908334c51SBrooks Davis     /// Constructs a new mock command.
mock_cmd(void)6008334c51SBrooks Davis     mock_cmd(void) :
6108334c51SBrooks Davis         cmdline::base_command< Data >("mock", "arg1 [arg2 [arg3]]", 1, 3,
6208334c51SBrooks Davis                                       "Command for testing."),
6308334c51SBrooks Davis         executed(false)
6408334c51SBrooks Davis     {
6508334c51SBrooks Davis         this->add_option(cmdline::string_option("the_string", "Test option",
6608334c51SBrooks Davis                                                 "arg"));
6708334c51SBrooks Davis     }
6808334c51SBrooks Davis 
6908334c51SBrooks Davis     /// Executes the command.
7008334c51SBrooks Davis     ///
7108334c51SBrooks Davis     /// \param cmdline Representation of the command line to the subcommand.
7208334c51SBrooks Davis     /// \param data Arbitrary data cookie passed to the command.
7308334c51SBrooks Davis     ///
7408334c51SBrooks Davis     /// \return A hardcoded number for testing purposes.
7508334c51SBrooks Davis     int
run(cmdline::ui *,const cmdline::parsed_cmdline & cmdline,const Data & data)7608334c51SBrooks Davis     run(cmdline::ui* /* ui */,
7708334c51SBrooks Davis         const cmdline::parsed_cmdline& cmdline, const Data& data)
7808334c51SBrooks Davis     {
7908334c51SBrooks Davis         if (cmdline.has_option("the_string"))
8008334c51SBrooks Davis             optvalue = cmdline.get_option< cmdline::string_option >(
8108334c51SBrooks Davis                 "the_string");
8208334c51SBrooks Davis         ATF_REQUIRE_EQ(ExpectedData, data);
8308334c51SBrooks Davis         executed = true;
8408334c51SBrooks Davis         return 1234;
8508334c51SBrooks Davis     }
8608334c51SBrooks Davis };
8708334c51SBrooks Davis 
8808334c51SBrooks Davis 
8908334c51SBrooks Davis /// Mock command to test the cmdline::base_command_no_data base class.
9008334c51SBrooks Davis class mock_cmd_no_data : public cmdline::base_command_no_data {
9108334c51SBrooks Davis public:
9208334c51SBrooks Davis     /// Indicates if run() has been called already and executed correctly.
9308334c51SBrooks Davis     bool executed;
9408334c51SBrooks Davis 
9508334c51SBrooks Davis     /// Contains the argument of --the_string after run() is executed.
9608334c51SBrooks Davis     std::string optvalue;
9708334c51SBrooks Davis 
9808334c51SBrooks Davis     /// Constructs a new mock command.
mock_cmd_no_data(void)9908334c51SBrooks Davis     mock_cmd_no_data(void) :
10008334c51SBrooks Davis         cmdline::base_command_no_data("mock", "arg1 [arg2 [arg3]]", 1, 3,
10108334c51SBrooks Davis                                       "Command for testing."),
10208334c51SBrooks Davis         executed(false)
10308334c51SBrooks Davis     {
10408334c51SBrooks Davis         add_option(cmdline::string_option("the_string", "Test option", "arg"));
10508334c51SBrooks Davis     }
10608334c51SBrooks Davis 
10708334c51SBrooks Davis     /// Executes the command.
10808334c51SBrooks Davis     ///
10908334c51SBrooks Davis     /// \param cmdline Representation of the command line to the subcommand.
11008334c51SBrooks Davis     ///
11108334c51SBrooks Davis     /// \return A hardcoded number for testing purposes.
11208334c51SBrooks Davis     int
run(cmdline::ui *,const cmdline::parsed_cmdline & cmdline)11308334c51SBrooks Davis     run(cmdline::ui* /* ui */,
11408334c51SBrooks Davis         const cmdline::parsed_cmdline& cmdline)
11508334c51SBrooks Davis     {
11608334c51SBrooks Davis         if (cmdline.has_option("the_string"))
11708334c51SBrooks Davis             optvalue = cmdline.get_option< cmdline::string_option >(
11808334c51SBrooks Davis                 "the_string");
11908334c51SBrooks Davis         executed = true;
12008334c51SBrooks Davis         return 1234;
12108334c51SBrooks Davis     }
12208334c51SBrooks Davis };
12308334c51SBrooks Davis 
12408334c51SBrooks Davis 
12508334c51SBrooks Davis /// Implementation of a command to get access to parse_cmdline().
12608334c51SBrooks Davis class parse_cmdline_portal : public cmdline::command_proto {
12708334c51SBrooks Davis public:
12808334c51SBrooks Davis     /// Constructs a new mock command.
parse_cmdline_portal(void)12908334c51SBrooks Davis     parse_cmdline_portal(void) :
13008334c51SBrooks Davis         cmdline::command_proto("portal", "arg1 [arg2 [arg3]]", 1, 3,
13108334c51SBrooks Davis                                "Command for testing.")
13208334c51SBrooks Davis     {
13308334c51SBrooks Davis         this->add_option(cmdline::string_option("the_string", "Test option",
13408334c51SBrooks Davis                                                 "arg"));
13508334c51SBrooks Davis     }
13608334c51SBrooks Davis 
13708334c51SBrooks Davis     /// Delegator for the internal parse_cmdline() method.
13808334c51SBrooks Davis     ///
13908334c51SBrooks Davis     /// \param args The input arguments to be parsed.
14008334c51SBrooks Davis     ///
14108334c51SBrooks Davis     /// \return The parsed command line, split in options and arguments.
14208334c51SBrooks Davis     cmdline::parsed_cmdline
operator ()(const cmdline::args_vector & args) const14308334c51SBrooks Davis     operator()(const cmdline::args_vector& args) const
14408334c51SBrooks Davis     {
14508334c51SBrooks Davis         return parse_cmdline(args);
14608334c51SBrooks Davis     }
14708334c51SBrooks Davis };
14808334c51SBrooks Davis 
14908334c51SBrooks Davis 
15008334c51SBrooks Davis }  // anonymous namespace
15108334c51SBrooks Davis 
15208334c51SBrooks Davis 
15308334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__ok);
ATF_TEST_CASE_BODY(command_proto__parse_cmdline__ok)15408334c51SBrooks Davis ATF_TEST_CASE_BODY(command_proto__parse_cmdline__ok)
15508334c51SBrooks Davis {
15608334c51SBrooks Davis     cmdline::args_vector args;
15708334c51SBrooks Davis     args.push_back("portal");
15808334c51SBrooks Davis     args.push_back("--the_string=foo bar");
15908334c51SBrooks Davis     args.push_back("one arg");
16008334c51SBrooks Davis     args.push_back("another arg");
16108334c51SBrooks Davis     (void)parse_cmdline_portal()(args);
16208334c51SBrooks Davis }
16308334c51SBrooks Davis 
16408334c51SBrooks Davis 
16508334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__parse_fail);
ATF_TEST_CASE_BODY(command_proto__parse_cmdline__parse_fail)16608334c51SBrooks Davis ATF_TEST_CASE_BODY(command_proto__parse_cmdline__parse_fail)
16708334c51SBrooks Davis {
16808334c51SBrooks Davis     cmdline::args_vector args;
16908334c51SBrooks Davis     args.push_back("portal");
17008334c51SBrooks Davis     args.push_back("--foo-bar");
17108334c51SBrooks Davis     ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar",
17208334c51SBrooks Davis                          (void)parse_cmdline_portal()(args));
17308334c51SBrooks Davis }
17408334c51SBrooks Davis 
17508334c51SBrooks Davis 
17608334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__args_invalid);
ATF_TEST_CASE_BODY(command_proto__parse_cmdline__args_invalid)17708334c51SBrooks Davis ATF_TEST_CASE_BODY(command_proto__parse_cmdline__args_invalid)
17808334c51SBrooks Davis {
17908334c51SBrooks Davis     cmdline::args_vector args;
18008334c51SBrooks Davis     args.push_back("portal");
18108334c51SBrooks Davis 
18208334c51SBrooks Davis     ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Not enough arguments",
18308334c51SBrooks Davis                          (void)parse_cmdline_portal()(args));
18408334c51SBrooks Davis 
18508334c51SBrooks Davis     args.push_back("1");
18608334c51SBrooks Davis     args.push_back("2");
18708334c51SBrooks Davis     args.push_back("3");
18808334c51SBrooks Davis     args.push_back("4");
18908334c51SBrooks Davis     ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Too many arguments",
19008334c51SBrooks Davis                          (void)parse_cmdline_portal()(args));
19108334c51SBrooks Davis }
19208334c51SBrooks Davis 
19308334c51SBrooks Davis 
19408334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(base_command__getters);
ATF_TEST_CASE_BODY(base_command__getters)19508334c51SBrooks Davis ATF_TEST_CASE_BODY(base_command__getters)
19608334c51SBrooks Davis {
19708334c51SBrooks Davis     mock_cmd< int, 584 > cmd;
19808334c51SBrooks Davis     ATF_REQUIRE_EQ("mock", cmd.name());
19908334c51SBrooks Davis     ATF_REQUIRE_EQ("arg1 [arg2 [arg3]]", cmd.arg_list());
20008334c51SBrooks Davis     ATF_REQUIRE_EQ("Command for testing.", cmd.short_description());
20108334c51SBrooks Davis     ATF_REQUIRE_EQ(1, cmd.options().size());
20208334c51SBrooks Davis     ATF_REQUIRE_EQ("the_string", cmd.options()[0]->long_name());
20308334c51SBrooks Davis }
20408334c51SBrooks Davis 
20508334c51SBrooks Davis 
20608334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(base_command__main__ok)
ATF_TEST_CASE_BODY(base_command__main__ok)20708334c51SBrooks Davis ATF_TEST_CASE_BODY(base_command__main__ok)
20808334c51SBrooks Davis {
20908334c51SBrooks Davis     mock_cmd< int, 584 > cmd;
21008334c51SBrooks Davis 
21108334c51SBrooks Davis     cmdline::ui_mock ui;
21208334c51SBrooks Davis     cmdline::args_vector args;
21308334c51SBrooks Davis     args.push_back("mock");
21408334c51SBrooks Davis     args.push_back("--the_string=foo bar");
21508334c51SBrooks Davis     args.push_back("one arg");
21608334c51SBrooks Davis     args.push_back("another arg");
21708334c51SBrooks Davis     ATF_REQUIRE_EQ(1234, cmd.main(&ui, args, 584));
21808334c51SBrooks Davis     ATF_REQUIRE(cmd.executed);
21908334c51SBrooks Davis     ATF_REQUIRE_EQ("foo bar", cmd.optvalue);
22008334c51SBrooks Davis }
22108334c51SBrooks Davis 
22208334c51SBrooks Davis 
22308334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(base_command__main__parse_cmdline_fail)
ATF_TEST_CASE_BODY(base_command__main__parse_cmdline_fail)22408334c51SBrooks Davis ATF_TEST_CASE_BODY(base_command__main__parse_cmdline_fail)
22508334c51SBrooks Davis {
22608334c51SBrooks Davis     mock_cmd< int, 584 > cmd;
22708334c51SBrooks Davis 
22808334c51SBrooks Davis     cmdline::ui_mock ui;
22908334c51SBrooks Davis     cmdline::args_vector args;
23008334c51SBrooks Davis     args.push_back("mock");
23108334c51SBrooks Davis     args.push_back("--foo-bar");
23208334c51SBrooks Davis     ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar",
23308334c51SBrooks Davis                          cmd.main(&ui, args, 584));
23408334c51SBrooks Davis     ATF_REQUIRE(!cmd.executed);
23508334c51SBrooks Davis }
23608334c51SBrooks Davis 
23708334c51SBrooks Davis 
23808334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__getters);
ATF_TEST_CASE_BODY(base_command_no_data__getters)23908334c51SBrooks Davis ATF_TEST_CASE_BODY(base_command_no_data__getters)
24008334c51SBrooks Davis {
24108334c51SBrooks Davis     mock_cmd_no_data cmd;
24208334c51SBrooks Davis     ATF_REQUIRE_EQ("mock", cmd.name());
24308334c51SBrooks Davis     ATF_REQUIRE_EQ("arg1 [arg2 [arg3]]", cmd.arg_list());
24408334c51SBrooks Davis     ATF_REQUIRE_EQ("Command for testing.", cmd.short_description());
24508334c51SBrooks Davis     ATF_REQUIRE_EQ(1, cmd.options().size());
24608334c51SBrooks Davis     ATF_REQUIRE_EQ("the_string", cmd.options()[0]->long_name());
24708334c51SBrooks Davis }
24808334c51SBrooks Davis 
24908334c51SBrooks Davis 
25008334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__main__ok)
ATF_TEST_CASE_BODY(base_command_no_data__main__ok)25108334c51SBrooks Davis ATF_TEST_CASE_BODY(base_command_no_data__main__ok)
25208334c51SBrooks Davis {
25308334c51SBrooks Davis     mock_cmd_no_data cmd;
25408334c51SBrooks Davis 
25508334c51SBrooks Davis     cmdline::ui_mock ui;
25608334c51SBrooks Davis     cmdline::args_vector args;
25708334c51SBrooks Davis     args.push_back("mock");
25808334c51SBrooks Davis     args.push_back("--the_string=foo bar");
25908334c51SBrooks Davis     args.push_back("one arg");
26008334c51SBrooks Davis     args.push_back("another arg");
26108334c51SBrooks Davis     ATF_REQUIRE_EQ(1234, cmd.main(&ui, args));
26208334c51SBrooks Davis     ATF_REQUIRE(cmd.executed);
26308334c51SBrooks Davis     ATF_REQUIRE_EQ("foo bar", cmd.optvalue);
26408334c51SBrooks Davis }
26508334c51SBrooks Davis 
26608334c51SBrooks Davis 
26708334c51SBrooks Davis 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)26808334c51SBrooks Davis ATF_TEST_CASE_BODY(base_command_no_data__main__parse_cmdline_fail)
26908334c51SBrooks Davis {
27008334c51SBrooks Davis     mock_cmd_no_data cmd;
27108334c51SBrooks Davis 
27208334c51SBrooks Davis     cmdline::ui_mock ui;
27308334c51SBrooks Davis     cmdline::args_vector args;
27408334c51SBrooks Davis     args.push_back("mock");
27508334c51SBrooks Davis     args.push_back("--foo-bar");
27608334c51SBrooks Davis     ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar",
27708334c51SBrooks Davis                          cmd.main(&ui, args));
27808334c51SBrooks Davis     ATF_REQUIRE(!cmd.executed);
27908334c51SBrooks Davis }
28008334c51SBrooks Davis 
28108334c51SBrooks Davis 
ATF_INIT_TEST_CASES(tcs)28208334c51SBrooks Davis ATF_INIT_TEST_CASES(tcs)
28308334c51SBrooks Davis {
28408334c51SBrooks Davis     ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__ok);
28508334c51SBrooks Davis     ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__parse_fail);
28608334c51SBrooks Davis     ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__args_invalid);
28708334c51SBrooks Davis 
28808334c51SBrooks Davis     ATF_ADD_TEST_CASE(tcs, base_command__getters);
28908334c51SBrooks Davis     ATF_ADD_TEST_CASE(tcs, base_command__main__ok);
29008334c51SBrooks Davis     ATF_ADD_TEST_CASE(tcs, base_command__main__parse_cmdline_fail);
29108334c51SBrooks Davis 
29208334c51SBrooks Davis     ATF_ADD_TEST_CASE(tcs, base_command_no_data__getters);
29308334c51SBrooks Davis     ATF_ADD_TEST_CASE(tcs, base_command_no_data__main__ok);
29408334c51SBrooks Davis     ATF_ADD_TEST_CASE(tcs, base_command_no_data__main__parse_cmdline_fail);
29508334c51SBrooks Davis }
296