| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- //
- // options_test.cpp
- // program_args-test
- //
- // Created by Sam Jaffe on 2/7/21.
- //
- #include "program_args/arguments.h"
- #include <filesystem>
- #include "xcode_gtest_helper.h"
- using testing::ElementsAre;
- using testing::Eq;
- using testing::IsEmpty;
- template <typename T, size_t N> static T parse(char const * const (&argv)[N]) {
- return T(N, argv);
- }
- struct LongOptionTest : program::Arguments<LongOptionTest> {
- using Arguments::Arguments;
- std::string endpoint = option("endpoint");
- int port = option("port");
- };
- TEST(LongOptionTest, ArgumentsAreDefaultedNaturally) {
- auto const options = parse<LongOptionTest>({""});
- EXPECT_THAT(options.endpoint, Eq(""));
- EXPECT_THAT(options.port, Eq(0));
- }
- TEST(LongOptionTest, CanProvideStringArgument) {
- auto const options = parse<LongOptionTest>({"", "--endpoint", "/null"});
- EXPECT_THAT(options.endpoint, Eq("/null"));
- }
- TEST(LongOptionTest, CanProvideNumericArgument) {
- auto const options = parse<LongOptionTest>({"", "--port", "443"});
- EXPECT_THAT(options.port, Eq(443));
- }
- TEST(LongOptionTest, WillThrowOnInvalidNumericArgument) {
- EXPECT_THROW(parse<LongOptionTest>({"", "--port", "one"}),
- program::ProgramArgumentsError);
- }
- TEST(LongOptionTest, WillThrowOnRepeatedArgument) {
- EXPECT_THROW(parse<LongOptionTest>({"", "--port", "8080", "--port", "443"}),
- program::ArgumentStructureError);
- }
- TEST(LongOptionTest, WillThrowOnUnknownArgument) {
- EXPECT_THROW(parse<LongOptionTest>({"", "--path", "/null"}),
- program::NotAnArgumentError);
- }
- TEST(LongOptionTest, DoesNotImplicitlyShortenArgs) {
- EXPECT_THROW(parse<LongOptionTest>({"", "-p", "443"}),
- program::NotAnArgumentError);
- }
- struct LongOptionWithDefaultTest
- : program::Arguments<LongOptionWithDefaultTest> {
- using Arguments::Arguments;
- std::string endpoint = option("endpoint") = "/default";
- int port = option("port") = 8080;
- };
- TEST(LongOptionWithDefaultTest, ArgumentsAreDefaultedNaturally) {
- auto const options = parse<LongOptionWithDefaultTest>({""});
- EXPECT_THAT(options.endpoint, Eq("/default"));
- EXPECT_THAT(options.port, Eq(8080));
- }
- TEST(LongOptionWithDefaultTest, CanProvideStringArgument) {
- auto const options =
- parse<LongOptionWithDefaultTest>({"", "--endpoint", "/null"});
- EXPECT_THAT(options.endpoint, Eq("/null"));
- }
- TEST(LongOptionWithDefaultTest, CanProvideNumericArgument) {
- auto const options = parse<LongOptionWithDefaultTest>({"", "--port", "443"});
- EXPECT_THAT(options.port, Eq(443));
- }
- struct LongOptionWithAbbrevTest : program::Arguments<LongOptionWithAbbrevTest> {
- using Arguments::Arguments;
- std::string endpoint = option("endpoint", 'e');
- int port = option("port", 'p');
- };
- TEST(LongOptionWithAbbrevTest, CanProvideStringArgument) {
- auto const options =
- parse<LongOptionWithAbbrevTest>({"", "--endpoint", "/null"});
- EXPECT_THAT(options.endpoint, Eq("/null"));
- }
- TEST(LongOptionWithAbbrevTest, CanProvideAbbrevStringArgument) {
- auto const options = parse<LongOptionWithAbbrevTest>({"", "-e", "/null"});
- EXPECT_THAT(options.endpoint, Eq("/null"));
- }
- TEST(LongOptionWithAbbrevTest, CanProvideNumericArgument) {
- auto const options = parse<LongOptionWithAbbrevTest>({"", "--port", "443"});
- EXPECT_THAT(options.port, Eq(443));
- }
- TEST(LongOptionWithAbbrevTest, CanProvideAbbrevNumericArgument) {
- auto const options = parse<LongOptionWithAbbrevTest>({"", "-p", "443"});
- EXPECT_THAT(options.port, Eq(443));
- }
- TEST(LongOptionWithAbbrevTest, ShortAndLongArgsGoToSamePool) {
- EXPECT_THROW(
- parse<LongOptionWithAbbrevTest>({"", "--port", "8080", "-p", "443"}),
- program::ArgumentStructureError);
- }
- TEST(LongOptionWithAbbrevTest, CanPutAbbrevArgAndValueInSameToken) {
- EXPECT_NO_THROW(parse<LongOptionWithAbbrevTest>({"", "-p443"}));
- auto const options = parse<LongOptionWithAbbrevTest>({"", "-p443"});
- EXPECT_THAT(options.port, Eq(443));
- }
- struct LongOptionRepeatTest : program::Arguments<LongOptionRepeatTest> {
- using Arguments::Arguments;
- std::vector<int> port = option("port");
- };
- TEST(LongOptionRepeatTest, DefaultIsEmpty) {
- auto const options = parse<LongOptionRepeatTest>({""});
- EXPECT_THAT(options.port, IsEmpty());
- }
- TEST(LongOptionRepeatTest, CanProvideArgument) {
- auto const options = parse<LongOptionRepeatTest>({"", "--port", "443"});
- EXPECT_THAT(options.port, ElementsAre(443));
- }
- TEST(LongOptionRepeatTest, RepeatingArgumentsAppends) {
- auto const options =
- parse<LongOptionRepeatTest>({"", "--port", "443", "--port", "8080"});
- EXPECT_THAT(options.port, ElementsAre(443, 8080));
- }
- struct LongOptionRepeatWithDefaultTest
- : program::Arguments<LongOptionRepeatWithDefaultTest> {
- using Arguments::Arguments;
- std::vector<int> port = option("port") = 8080;
- std::vector<int> default_ports = option("default_ports") = {80, 443};
- };
- TEST(LongOptionRepeatWithDefaultTest, DefaultIsProvided) {
- auto const options = parse<LongOptionRepeatWithDefaultTest>({""});
- EXPECT_THAT(options.port, ElementsAre(8080));
- EXPECT_THAT(options.default_ports, ElementsAre(80, 443));
- }
- TEST(LongOptionRepeatWithDefaultTest, ArgumentOverwritesDefault) {
- auto const options =
- parse<LongOptionRepeatWithDefaultTest>({"", "--port", "443"});
- EXPECT_THAT(options.port, ElementsAre(443));
- }
- namespace fs = std::filesystem;
- struct DeferOptionTest : program::Arguments<DeferOptionTest> {
- using Arguments::Arguments;
- fs::path path = option("path") = ".";
- fs::path log = option("log") = PROGRAM_DEFER(path / "test.log");
- };
- TEST(DeferOptionTest, DefaultResolves) {
- auto const options = parse<DeferOptionTest>({""});
- EXPECT_THAT(options.log.string(), "./test.log");
- }
- TEST(DeferOptionTest, CapturesUpdateToDependent) {
- auto const options = parse<DeferOptionTest>({"", "--path", "/var/log"});
- EXPECT_THAT(options.log.string(), "/var/log/test.log");
- }
- TEST(DeferOptionTest, SettingActualArgWillOverwrite) {
- auto const options =
- parse<DeferOptionTest>({"", "--path", "/var/log", "--log", "test.log"});
- EXPECT_THAT(options.log.string(), "test.log");
- }
- struct ShortOptionTest : program::Arguments<ShortOptionTest> {
- using Arguments::Arguments;
- int arg = option('n');
- };
- TEST(ShortOptionTest, DoesNotAllowDoubleDash) {
- EXPECT_THROW(parse<ShortOptionTest>({"", "--n", "5"}),
- program::NotAnArgumentError);
- }
- TEST(ShortOptionTest, CanConstructWithOnlyAbbrev) {
- auto const options = parse<ShortOptionTest>({"", "-n", "5"});
- EXPECT_THAT(options.arg, 5);
- }
- struct GeneratedDefaultTest : program::Arguments<GeneratedDefaultTest> {
- using Arguments::Arguments;
- std::string pwd = option('C');
- std::string git_dir = option("git-dir") = PROGRAM_DEFER(pwd + "/.git");
- int arg = option('n') = []() { return 7; };
- };
- TEST(GeneratedDefaultTest, DefaultCanComeFromFunction) {
- auto const options = parse<GeneratedDefaultTest>({""});
- EXPECT_THAT(options.arg, 7);
- }
- TEST(GeneratedDefaultTest, CanSetValue) {
- auto const options = parse<GeneratedDefaultTest>({"", "-n", "5"});
- EXPECT_THAT(options.arg, 5);
- }
- TEST(GeneratedDefaultTest, CanReferenceThis) {
- auto const options =
- parse<GeneratedDefaultTest>({"", "-C", "/opt/local/bin"});
- EXPECT_THAT(options.pwd, "/opt/local/bin");
- EXPECT_THAT(options.git_dir, "/opt/local/bin/.git");
- }
- struct CompoundOptionsTest : program::Arguments<CompoundOptionsTest> {
- using Arguments::Arguments;
- std::pair<int, int> screen_size =
- std::make_pair(option("width"), option("height"));
- };
- TEST(CompoundOptionsTest, CanBindTupleElements) {
- auto const options =
- parse<CompoundOptionsTest>({"", "--width", "1920", "--height", "1080"});
- EXPECT_THAT(options.screen_size.first, 1920);
- EXPECT_THAT(options.screen_size.second, 1080);
- }
- struct dim2 {
- int x, y;
- };
- template <> struct string_utils::cast_helper<dim2> {
- bool operator()(std::string_view str, dim2 & out) {
- return sscanf(str.data(), "%dx%d", &out.x, &out.y) == 2;
- }
- };
- struct ParsedOptionTest : program::Arguments<ParsedOptionTest> {
- using Arguments::Arguments;
- dim2 screen_size = option("screen");
- };
- TEST(ParsedOptionTest, CanInvokeSpecialParser) {
- auto const options = parse<ParsedOptionTest>({"", "--screen", "1920x1080"});
- EXPECT_THAT(options.screen_size.x, 1920);
- EXPECT_THAT(options.screen_size.y, 1080);
- }
- TEST(ParsedOptionTest, SpecialParserCanFail) {
- EXPECT_THROW(parse<ParsedOptionTest>({"", "--screen", "1920"}),
- program::ArgumentStructureError);
- }
|