mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
* change the move function to _move_option and add an additional test add a validation check on min options to make sure it is even possible to succeed. add some additional tests to cover code paths and potential errors. add a number of additional tests and checks and fix some issues with the add function in option_groups clean up example and help formatting add option_groups example to play with move create_option_group to a member function using a dummy template add some optionGroup tests add min and max options calls and an associated Error call * add ranges example, add excludes to app for options and subcommands. * add some tests on ranges, and some subcommand tests with exclusion * add tests in optionGroups for some invalid inputs * add required option to subcommands and option_groups * add disabled flag * add disable option to subcommands and some more tests * start work on ReadMe modifications * update the readme with descriptions of function and methods added for option_groups * clear up gcc 4.7 warnings * some update to the Readme and a few more warnings fixed * Minor readme touchup
504 lines
14 KiB
C++
504 lines
14 KiB
C++
#include "app_helper.hpp"
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using ::testing::HasSubstr;
|
|
using ::testing::Not;
|
|
|
|
using vs_t = std::vector<std::string>;
|
|
|
|
TEST_F(TApp, BasicOptionGroup) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
|
|
args = {"--test1", "5"};
|
|
run();
|
|
EXPECT_EQ(res, 5);
|
|
EXPECT_EQ(app.count_all(), 1u);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupExact) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option(1);
|
|
args = {"--test1", "5"};
|
|
run();
|
|
EXPECT_EQ(res, 5);
|
|
|
|
args = {"--test1", "5", "--test2", "4"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
std::string help = ogroup->help();
|
|
auto exactloc = help.find("[Exactly 1");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupExactTooMany) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option(10);
|
|
args = {"--test1", "5"};
|
|
EXPECT_THROW(run(), CLI::InvalidError);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupMinMax) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option(1, 1);
|
|
args = {"--test1", "5"};
|
|
run();
|
|
EXPECT_EQ(res, 5);
|
|
|
|
args = {"--test1", "5", "--test2", "4"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
std::string help = ogroup->help();
|
|
auto exactloc = help.find("[Exactly 1");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupMinMaxDifferent) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option(1, 2);
|
|
args = {"--test1", "5"};
|
|
run();
|
|
EXPECT_EQ(res, 5);
|
|
|
|
args = {"--test1", "5", "--test2", "4"};
|
|
EXPECT_NO_THROW(run());
|
|
EXPECT_EQ(app.count_all(), 2);
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--test1", "5", "--test2", "4", "--test3=5"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
std::string help = ogroup->help();
|
|
auto exactloc = help.find("[Between 1 and 2");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupMinMaxDifferentReversed) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option(2, 1);
|
|
EXPECT_EQ(ogroup->get_require_option_min(), 2);
|
|
EXPECT_EQ(ogroup->get_require_option_max(), 1);
|
|
args = {"--test1", "5"};
|
|
EXPECT_THROW(run(), CLI::InvalidError);
|
|
ogroup->require_option(1, 2);
|
|
EXPECT_NO_THROW(run());
|
|
EXPECT_EQ(res, 5);
|
|
EXPECT_EQ(ogroup->get_require_option_min(), 1);
|
|
EXPECT_EQ(ogroup->get_require_option_max(), 2);
|
|
args = {"--test1", "5", "--test2", "4"};
|
|
EXPECT_NO_THROW(run());
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--test1", "5", "--test2", "4", "--test3=5"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
std::string help = ogroup->help();
|
|
auto exactloc = help.find("[Between 1 and 2");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupMax) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option(-2);
|
|
args = {"--test1", "5"};
|
|
run();
|
|
EXPECT_EQ(res, 5);
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_NO_THROW(run());
|
|
|
|
args = {"--test1", "5", "--test2", "4", "--test3=5"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
std::string help = ogroup->help();
|
|
auto exactloc = help.find("[At most 2");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupMax1) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option(-1);
|
|
args = {"--test1", "5"};
|
|
run();
|
|
EXPECT_EQ(res, 5);
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_NO_THROW(run());
|
|
|
|
args = {"--test1", "5", "--test2", "4"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
std::string help = ogroup->help();
|
|
auto exactloc = help.find("[At most 1");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupMin) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option();
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--test1", "5", "--test2", "4", "--test3=5"};
|
|
EXPECT_NO_THROW(run());
|
|
|
|
std::string help = ogroup->help();
|
|
auto exactloc = help.find("[At least 1");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupExact2) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option(2);
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--test1", "5", "--test2", "4", "--test3=5"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--test1", "5", "--test3=5"};
|
|
EXPECT_NO_THROW(run());
|
|
|
|
std::string help = ogroup->help();
|
|
auto exactloc = help.find("[Exactly 2");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupMin2) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
int res;
|
|
ogroup->add_option("--test1", res);
|
|
ogroup->add_option("--test2", res);
|
|
ogroup->add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
ogroup->require_option(2, 0);
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--test1", "5", "--test2", "4", "--test3=5"};
|
|
EXPECT_NO_THROW(run());
|
|
|
|
std::string help = ogroup->help();
|
|
auto exactloc = help.find("[At least 2");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupMinMoved) {
|
|
|
|
int res;
|
|
auto opt1 = app.add_option("--test1", res);
|
|
auto opt2 = app.add_option("--test2", res);
|
|
auto opt3 = app.add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
|
|
auto ogroup = app.add_option_group("clusters");
|
|
ogroup->require_option();
|
|
ogroup->add_option(opt1);
|
|
ogroup->add_option(opt2);
|
|
ogroup->add_option(opt3);
|
|
|
|
args = {"--option", "9"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--test1", "5", "--test2", "4", "--test3=5"};
|
|
EXPECT_NO_THROW(run());
|
|
|
|
std::string help = app.help();
|
|
auto exactloc = help.find("[At least 1");
|
|
auto oloc = help.find("--test1");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
EXPECT_NE(oloc, std::string::npos);
|
|
EXPECT_LT(exactloc, oloc);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupMinMovedAsGroup) {
|
|
|
|
int res;
|
|
auto opt1 = app.add_option("--test1", res);
|
|
auto opt2 = app.add_option("--test2", res);
|
|
auto opt3 = app.add_option("--test3", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
|
|
auto ogroup = app.add_option_group("clusters");
|
|
ogroup->require_option();
|
|
ogroup->add_options(opt1, opt2, opt3);
|
|
|
|
EXPECT_THROW(ogroup->add_options(opt1), CLI::OptionNotFound);
|
|
args = {"--option", "9"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--test1", "5", "--test2", "4", "--test3=5"};
|
|
EXPECT_NO_THROW(run());
|
|
|
|
std::string help = app.help();
|
|
auto exactloc = help.find("[At least 1");
|
|
auto oloc = help.find("--test1");
|
|
EXPECT_NE(exactloc, std::string::npos);
|
|
EXPECT_NE(oloc, std::string::npos);
|
|
EXPECT_LT(exactloc, oloc);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupAddFailures) {
|
|
|
|
int res;
|
|
auto opt1 = app.add_option("--test1", res);
|
|
app.set_config("--config");
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
|
|
auto ogroup = app.add_option_group("clusters");
|
|
EXPECT_THROW(ogroup->add_options(app.get_config_ptr()), CLI::OptionAlreadyAdded);
|
|
EXPECT_THROW(ogroup->add_options(app.get_help_ptr()), CLI::OptionAlreadyAdded);
|
|
|
|
auto sub = app.add_subcommand("sub", "subcommand");
|
|
auto opt2 = sub->add_option("--option2", val2);
|
|
|
|
EXPECT_THROW(ogroup->add_option(opt2), CLI::OptionNotFound);
|
|
|
|
EXPECT_THROW(ogroup->add_options(nullptr), CLI::OptionNotFound);
|
|
|
|
ogroup->add_option(opt1);
|
|
|
|
auto opt3 = app.add_option("--test1", res);
|
|
|
|
EXPECT_THROW(ogroup->add_option(opt3), CLI::OptionAlreadyAdded);
|
|
}
|
|
|
|
TEST_F(TApp, BasicOptionGroupScrewedUpMove) {
|
|
|
|
int res;
|
|
auto opt1 = app.add_option("--test1", res);
|
|
auto opt2 = app.add_option("--test2", res);
|
|
int val2;
|
|
app.add_option("--option", val2);
|
|
|
|
auto ogroup = app.add_option_group("clusters");
|
|
ogroup->require_option();
|
|
auto ogroup2 = ogroup->add_option_group("clusters2");
|
|
EXPECT_THROW(ogroup2->add_options(opt1, opt2), CLI::OptionNotFound);
|
|
|
|
CLI::Option_group EmptyGroup("description", "new group", nullptr);
|
|
|
|
EXPECT_THROW(EmptyGroup.add_option(opt2), CLI::OptionNotFound);
|
|
EXPECT_THROW(app._move_option(opt2, ogroup2), CLI::OptionNotFound);
|
|
}
|
|
|
|
TEST_F(TApp, InvalidOptions) {
|
|
auto ogroup = app.add_option_group("clusters");
|
|
CLI::Option *opt = nullptr;
|
|
EXPECT_THROW(ogroup->excludes(opt), CLI::OptionNotFound);
|
|
CLI::App *app_p = nullptr;
|
|
EXPECT_THROW(ogroup->excludes(app_p), CLI::OptionNotFound);
|
|
EXPECT_THROW(ogroup->excludes(ogroup), CLI::OptionNotFound);
|
|
EXPECT_THROW(ogroup->add_option(opt), CLI::OptionNotFound);
|
|
}
|
|
|
|
struct ManyGroups : public TApp {
|
|
|
|
CLI::Option_group *main;
|
|
CLI::Option_group *g1;
|
|
CLI::Option_group *g2;
|
|
CLI::Option_group *g3;
|
|
std::string name1;
|
|
std::string name2;
|
|
std::string name3;
|
|
std::string val1;
|
|
std::string val2;
|
|
std::string val3;
|
|
ManyGroups() {
|
|
main = app.add_option_group("main", "the main outer group");
|
|
g1 = main->add_option_group("g1", "group1 description");
|
|
g2 = main->add_option_group("g2", "group2 description");
|
|
g3 = main->add_option_group("g3", "group3 description");
|
|
g1->add_option("--name1", name1)->required();
|
|
g1->add_option("--val1", val1);
|
|
g2->add_option("--name2", name2)->required();
|
|
g2->add_option("--val2", val2);
|
|
g3->add_option("--name3", name3)->required();
|
|
g3->add_option("--val3", val3);
|
|
}
|
|
|
|
void remove_required() {
|
|
g1->get_option("--name1")->required(false);
|
|
g2->get_option("--name2")->required(false);
|
|
g3->get_option("--name3")->required(false);
|
|
g1->required(false);
|
|
g2->required(false);
|
|
g3->required(false);
|
|
}
|
|
};
|
|
|
|
TEST_F(ManyGroups, SingleGroup) {
|
|
// only 1 group can be used
|
|
main->require_option(1);
|
|
args = {"--name1", "test"};
|
|
run();
|
|
EXPECT_EQ(name1, "test");
|
|
|
|
args = {"--name2", "test", "--val2", "tval"};
|
|
|
|
run();
|
|
EXPECT_EQ(val2, "tval");
|
|
|
|
args = {"--name1", "test", "--val2", "tval"};
|
|
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
}
|
|
|
|
TEST_F(ManyGroups, SingleGroupError) {
|
|
// only 1 group can be used
|
|
main->require_option(1);
|
|
args = {"--name1", "test", "--name2", "test3"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
}
|
|
|
|
TEST_F(ManyGroups, AtMostOneGroup) {
|
|
// only 1 group can be used
|
|
main->require_option(0, 1);
|
|
args = {"--name1", "test", "--name2", "test3"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {};
|
|
EXPECT_NO_THROW(run());
|
|
}
|
|
|
|
TEST_F(ManyGroups, AtLeastTwoGroups) {
|
|
// only 1 group can be used
|
|
main->require_option(2, 0);
|
|
args = {"--name1", "test", "--name2", "test3"};
|
|
run();
|
|
|
|
args = {"--name1", "test"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
}
|
|
|
|
TEST_F(ManyGroups, BetweenOneAndTwoGroups) {
|
|
// only 1 group can be used
|
|
main->require_option(1, 2);
|
|
args = {"--name1", "test", "--name2", "test3"};
|
|
run();
|
|
|
|
args = {"--name1", "test"};
|
|
run();
|
|
|
|
args = {};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
|
|
args = {"--name1", "test", "--name2", "test3", "--name3=test3"};
|
|
EXPECT_THROW(run(), CLI::RequiredError);
|
|
}
|
|
|
|
TEST_F(ManyGroups, RequiredFirst) {
|
|
// only 1 group can be used
|
|
remove_required();
|
|
g1->required();
|
|
|
|
EXPECT_TRUE(g1->get_required());
|
|
EXPECT_FALSE(g2->get_required());
|
|
args = {"--name1", "test", "--name2", "test3"};
|
|
run();
|
|
|
|
args = {"--name2", "test"};
|
|
try {
|
|
run();
|
|
} catch(const CLI::RequiredError &re) {
|
|
EXPECT_THAT(re.what(), HasSubstr("g1"));
|
|
}
|
|
|
|
args = {"--name1", "test", "--name2", "test3", "--name3=test3"};
|
|
EXPECT_NO_THROW(run());
|
|
}
|
|
|
|
TEST_F(ManyGroups, DisableFirst) {
|
|
// only 1 group can be used
|
|
remove_required();
|
|
g1->disabled();
|
|
|
|
EXPECT_TRUE(g1->get_disabled());
|
|
EXPECT_FALSE(g2->get_disabled());
|
|
args = {"--name2", "test"};
|
|
|
|
run();
|
|
|
|
args = {"--name1", "test", "--name2", "test3"};
|
|
EXPECT_THROW(run(), CLI::ExtrasError);
|
|
g1->disabled(false);
|
|
args = {"--name1", "test", "--name2", "test3", "--name3=test3"};
|
|
EXPECT_NO_THROW(run());
|
|
}
|