diff --git a/src/mainspaceparser/mainspaceparser.cpp b/src/mainspaceparser/mainspaceparser.cpp index cfd2f79..7691a1f 100644 --- a/src/mainspaceparser/mainspaceparser.cpp +++ b/src/mainspaceparser/mainspaceparser.cpp @@ -96,10 +96,10 @@ MainSpaceParser::Status MainSpaceParser::parse(int argc, const char ** argv, Spa } -MainSpaceParser::Status MainSpaceParser::parse(int argc, const char ** argv, Space & out_space, const Space & options) +MainSpaceParser::Status MainSpaceParser::parse(int argc, const char ** argv, Space & out_space, const Space & arguments) { space = &out_space; - arguments_required_space = &options;; + arguments_required_space = &arguments;; return parse(argc, argv); } @@ -109,6 +109,7 @@ MainSpaceParser::Status MainSpaceParser::parse(int argc, const char ** argv) { last_status = status_ok; last_error_option.clear(); + space->set_empty_object(); for(size_t i=1 ; i < (size_t)argc && last_status == status_ok ; ) { diff --git a/src/mainspaceparser/mainspaceparser.h b/src/mainspaceparser/mainspaceparser.h index a7d9215..9c817d3 100644 --- a/src/mainspaceparser/mainspaceparser.h +++ b/src/mainspaceparser/mainspaceparser.h @@ -101,7 +101,7 @@ public: * */ Status parse(int argc, const char ** argv, Space & out_space); - Status parse(int argc, const char ** argv, Space & out_space, const Space & options); + Status parse(int argc, const char ** argv, Space & out_space, const Space & arguments); /* diff --git a/tests/main.cpp b/tests/main.cpp index f0db839..6ef5b07 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -40,6 +40,7 @@ #include + namespace pt { bool was_error = false; @@ -48,7 +49,7 @@ const char * test_msg = nullptr; } -int main() +int main(int argc, const char ** argv) { pt::pt_convert_tests::make_tests(); pt::pt_mainargsparser_tests::make_tests(); diff --git a/tests/mainargsparser.cpp b/tests/mainargsparser.cpp index 2876422..6763364 100644 --- a/tests/mainargsparser.cpp +++ b/tests/mainargsparser.cpp @@ -40,7 +40,7 @@ #include "test.h" #include "mainspaceparser/mainspaceparser.h" #include "utf8/utf8.h" - +#include "convert/convert.h" namespace pt { @@ -52,87 +52,279 @@ using namespace PT; namespace pt_mainargsparser_tests { -void test_text1() +struct MainSpaceParserOutputTest +{ + MainSpaceParser::Status status; + const char * option_err; + const char * json; +}; + + +void print_status(MainSpaceParser::Status status) +{ + if( status == MainSpaceParser::status_ok ) + { + std::cout << "MainSpaceParser::status_ok"; + } + else + if( status == MainSpaceParser::status_argument_not_provided ) + { + std::cout << "MainSpaceParser::status_argument_not_provided"; + } + else + if( status == MainSpaceParser::status_argument_provided ) + { + std::cout << "MainSpaceParser::status_argument_provided"; + } +} + + +bool has_space_in_str(const char * arg) +{ + while( *arg ) + { + if( PT::is_white((wchar_t)*arg) ) + return true; + + arg += 1; + } + + return false; +} + + +void print_args(int to_index, const char ** argv) +{ + for(int i=0 ; i <= to_index ; ++i) + { + bool has_space = has_space_in_str(argv[i]); + + if( has_space ) + std::cout << "\""; + + std::cout << argv[i]; + + if( has_space ) + std::cout << "\""; + + std::cout << " "; + } + + std::cout << std::endl; +} + + + +void test_mainargsparser(size_t len, const char ** argv, const Space & arguments_required, MainSpaceParserOutputTest * output) { reset_test_counter("mainargsparser"); + std::cout << "Testing MainArgsParser" << std::endl; MainSpaceParser parser; Space space; - const char * argv[] = { - "program_name", - "-a", - "-", - "-b", - "-c", - "-d", - "param for d", - "-b", - "--long", - "--foo", - "foo-one", - "foo-two", - "--long-param", - "--bar", - "bar1", - "bar2", - "bar3", - "-x", - "--piggy2=swinka2", - "--swinka3", - "--bar", - "xbar1", - "xbar2", - "xbar3", - }; + /* + * set to true when creating new tests (you can copy console output to the cpp file) + */ + bool prepare_tests = false; - - - - MainSpaceParser::Status status; - - - Space params; - params.add(L"d", 1); - params.add(L"foo", 2); - params.add(L"bar", 3); - params.add(L"piggy", 1); - params.add(L"piggy2", 1); - - size_t len = sizeof(argv) / sizeof(const char *); - - status = parser.parse(len, argv, space, params); - - - if( status != MainSpaceParser::status_ok ) + for(size_t i = 0 ; i < len ; ++i) { - std::wstring & err = parser.get_wrong_option(); + if( !prepare_tests ) + print_args(i, argv); + + MainSpaceParser::Status status = parser.parse(i + 1, argv, space, arguments_required); + + std::wstring & err_wstr = parser.get_wrong_option(); std::string err_str; - WideToUTF8(err, err_str); - std::cout << "blad: " << (int)status << ": " << err_str << std::endl; + WideToUTF8(err_wstr, err_str); + + std::string json; + space.serialize_to_json_to(json); + + std::cout << "{"; + print_status(status); + std::cout << ", " << "\"" << err_str << "\", " << "R\"json(" << json << ")json\"" << "}," << std::endl; + + if( !prepare_tests ) + { + test("status", status, output[i].status); + test("err_arg", err_str.c_str(), output[i].option_err); + test("json", json.c_str(), output[i].json); + } } - - test(status, MainSpaceParser::status_ok); - std::cout << space.serialize_to_json_str() << std::endl; - } +void test_mainargsparser1() +{ + const char * argv[] = { + "program_name", + "-a", + "-b", + "-c", + "-d", + "argument for d", + "-b", + "--long", + "--foo", + "foo-one", + "foo-two", + "--long-option", + "--bar", + "bar1", + "bar2", + "bar3", + "-x", + "--piggy2=option_for_piggy2", + "--piggy3", + "--bar", + "xbar1", + "xbar2", + "xbar3", + "--piggy2 another_option_for_piggy2", + "--", + "non-option-argument1", + "non-option-argument2", + "non-option-argument3", + }; + + MainSpaceParserOutputTest output[] = { + {MainSpaceParser::status_ok, "", R"json({})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[]],"c":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "d", R"json({"a":[[]],"b":[[]],"c":[[]],"d":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[]],"c":[[]],"d":[["argument for d"]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"c":[[]],"d":[["argument for d"]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"c":[[]],"d":[["argument for d"]],"long":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "foo", R"json({"a":[[]],"b":[[],[]],"c":[[]],"d":[["argument for d"]],"foo":[[]],"long":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "foo", R"json({"a":[[]],"b":[[],[]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one"]],"long":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "bar", R"json({"a":[[]],"b":[[],[]],"bar":[[]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "bar", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "bar", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2","bar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2","bar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2","bar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"x":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2","bar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy3":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "bar", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2","bar3"],[]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy3":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "bar", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2","bar3"],["xbar1"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy3":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "bar", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2","bar3"],["xbar1","xbar2"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy3":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2","bar3"],["xbar1","xbar2","xbar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy3":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"b":[[],[]],"bar":[["bar1","bar2","bar3"],["xbar1","xbar2","xbar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy2 another_option_for_piggy2":[[]],"piggy3":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"args":[],"b":[[],[]],"bar":[["bar1","bar2","bar3"],["xbar1","xbar2","xbar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy2 another_option_for_piggy2":[[]],"piggy3":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"args":["non-option-argument1"],"b":[[],[]],"bar":[["bar1","bar2","bar3"],["xbar1","xbar2","xbar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy2 another_option_for_piggy2":[[]],"piggy3":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"args":["non-option-argument1","non-option-argument2"],"b":[[],[]],"bar":[["bar1","bar2","bar3"],["xbar1","xbar2","xbar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy2 another_option_for_piggy2":[[]],"piggy3":[[]],"x":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"args":["non-option-argument1","non-option-argument2","non-option-argument3"],"b":[[],[]],"bar":[["bar1","bar2","bar3"],["xbar1","xbar2","xbar3"]],"c":[[]],"d":[["argument for d"]],"foo":[["foo-one","foo-two"]],"long":[[]],"long-option":[[]],"piggy2":[["option_for_piggy2"]],"piggy2 another_option_for_piggy2":[[]],"piggy3":[[]],"x":[[]]})json"}, + }; + + Space arguments_required; + arguments_required.add(L"d", 1); + arguments_required.add(L"foo", 2); + arguments_required.add(L"bar", 3); + arguments_required.add(L"piggy", 1); + arguments_required.add(L"piggy2", 1); + + size_t len = sizeof(argv) / sizeof(const char *); + test_mainargsparser(len, argv, arguments_required, output); +} +void test_mainargsparser2() +{ + const char * argv[] = { + "program_name", + "--long1", + "--long2=with-argument", + "--long3", + "-a", + "--=option-for-empty-argument", + "-b", + "arg b 1", + "arg b 2", + "-c", + "-f file-name with spaces", + "--xxx", + "arg 1", + "arg 2", + "arg 3", + "-", /* first non-option argument */ + "non-option-argument2", + "non-option-argument3", + "non-option-argument4", + }; + + MainSpaceParserOutputTest output[] = { + {MainSpaceParser::status_ok, "", R"json({})json"}, + {MainSpaceParser::status_ok, "", R"json({"long1":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"long1":[[]],"long2":[["with-argument"]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"long1":[[]],"long2":[["with-argument"]],"long3":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"a":[[]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"":[["option-for-empty-argument"]],"a":[[]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "b", R"json({"":[["option-for-empty-argument"]],"a":[[]],"b":[[]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "b", R"json({"":[["option-for-empty-argument"]],"a":[[]],"b":[["arg b 1"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"":[["option-for-empty-argument"]],"a":[[]],"b":[["arg b 1","arg b 2"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"":[["option-for-empty-argument"]],"a":[[]],"b":[["arg b 1","arg b 2"]],"c":[[]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"":[["option-for-empty-argument"]],"a":[[]],"b":[["arg b 1","arg b 2"]],"c":[[]],"f":[[" file-name with spaces"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "xxx", R"json({"":[["option-for-empty-argument"]],"a":[[]],"b":[["arg b 1","arg b 2"]],"c":[[]],"f":[[" file-name with spaces"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]],"xxx":[[]]})json"}, + {MainSpaceParser::status_argument_not_provided, "xxx", R"json({"":[["option-for-empty-argument"]],"a":[[]],"b":[["arg b 1","arg b 2"]],"c":[[]],"f":[[" file-name with spaces"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]],"xxx":[["arg 1"]]})json"}, + {MainSpaceParser::status_argument_not_provided, "xxx", R"json({"":[["option-for-empty-argument"]],"a":[[]],"b":[["arg b 1","arg b 2"]],"c":[[]],"f":[[" file-name with spaces"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]],"xxx":[["arg 1","arg 2"]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"":[["option-for-empty-argument"]],"a":[[]],"b":[["arg b 1","arg b 2"]],"c":[[]],"f":[[" file-name with spaces"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]],"xxx":[["arg 1","arg 2","arg 3"]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"":[["option-for-empty-argument"]],"a":[[]],"args":["-"],"b":[["arg b 1","arg b 2"]],"c":[[]],"f":[[" file-name with spaces"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]],"xxx":[["arg 1","arg 2","arg 3"]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"":[["option-for-empty-argument"]],"a":[[]],"args":["-","non-option-argument2"],"b":[["arg b 1","arg b 2"]],"c":[[]],"f":[[" file-name with spaces"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]],"xxx":[["arg 1","arg 2","arg 3"]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"":[["option-for-empty-argument"]],"a":[[]],"args":["-","non-option-argument2","non-option-argument3"],"b":[["arg b 1","arg b 2"]],"c":[[]],"f":[[" file-name with spaces"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]],"xxx":[["arg 1","arg 2","arg 3"]]})json"}, + {MainSpaceParser::status_ok, "", R"json({"":[["option-for-empty-argument"]],"a":[[]],"args":["-","non-option-argument2","non-option-argument3","non-option-argument4"],"b":[["arg b 1","arg b 2"]],"c":[[]],"f":[[" file-name with spaces"]],"long1":[[]],"long2":[["with-argument"]],"long3":[[]],"xxx":[["arg 1","arg 2","arg 3"]]})json"}, + }; + + Space arguments_required; + arguments_required.add(L"long2", 1); + arguments_required.add(L"b", 2); + arguments_required.add(L"f", 1); + arguments_required.add(L"xxx", 3); + arguments_required.add(L"", 1); + + size_t len = sizeof(argv) / sizeof(const char *); + test_mainargsparser(len, argv, arguments_required, output); +} + + + +void test_mainargsparser3() +{ + const char * argv[] = { + "program_name", + "--long1", + "--long2=with-argument", + "--long3", + }; + + MainSpaceParserOutputTest output[] = { + {MainSpaceParser::status_ok, "", R"json({})json"}, + {MainSpaceParser::status_ok, "", R"json({"long1":[[]]})json"}, + {MainSpaceParser::status_argument_provided, "long2", R"json({"long1":[[]]})json"}, + {MainSpaceParser::status_argument_provided, "long2", R"json({"long1":[[]]})json"}, + }; + + Space arguments_required; + arguments_required.add(L"non-existing", 1); + + size_t len = sizeof(argv) / sizeof(const char *); + test_mainargsparser(len, argv, arguments_required, output); +} + void make_tests() { - test_text1(); -// test_text2(); -// test_text3(); -// test_text4(); -// test_text5(); + test_mainargsparser1(); + test_mainargsparser2(); + test_mainargsparser3(); }