diff options
Diffstat (limited to 'cli/cli-test.c')
-rw-r--r-- | cli/cli-test.c | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/cli/cli-test.c b/cli/cli-test.c new file mode 100644 index 0000000..5af572c --- /dev/null +++ b/cli/cli-test.c @@ -0,0 +1,524 @@ +#include "cli.h" +#include "../utest/utest.h" +#include "../utils.h" + +/** + * MUTSTR - hack to "force" string literals to be mutable. + * @literal: a C string literal. + */ +#define MUTSTR(literal) \ + ({ \ + static char _s[] = literal; \ + _s; \ + }) + +TEST_BEGIN(test_parse_long) +{ + struct vars { + long i; + unsigned long u; + const char *s; + bool f; + } vars; + struct cli_opt options[] = { + { + .type = CLI_OT_INT, + .lon = "signed", + .value.i = &vars.i, + }, + { + .type = CLI_OT_FLAG, + .lon = "flag", + .value.f = &vars.f, + }, + { + .type = CLI_OT_UINT, + .lon = "unsigned", + .value.u = &vars.u, + }, + { + .type = CLI_OT_STRING, + .lon = "string", + .value.s = &vars.s, + }, + {0}, + }; + struct tcase { + int argc; + char *argv[2]; + struct vars expected_vars; + enum cli_rc expected_rc; + } cases[] = { + { + .argc = 2, + .argv = + { + MUTSTR("--signed"), + MUTSTR("-2"), + }, + .expected_vars = + { + .i = -2, + .u = 0, + .s = NULL, + .f = 0, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 2, + .argv = + { + MUTSTR("--flag"), + MUTSTR("--unsigned=42"), + }, + .expected_vars = + { + .i = 0, + .u = 0, + .s = NULL, + .f = true, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 1, + .argv = + { + MUTSTR("--unsigned=42"), + }, + .expected_vars = + { + .i = 0, + .u = 42, + .s = NULL, + .f = false, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 1, + .argv = + { + MUTSTR("--signed=0xB00B"), + }, + .expected_vars = + { + .i = 0xB00B, + .u = 0, + .s = NULL, + .f = false, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 2, + .argv = + { + MUTSTR("--string"), + MUTSTR("wololo"), + }, + .expected_vars = + { + .i = 0, + .u = 0, + .s = "wololo", + .f = false, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 1, + .argv = + { + MUTSTR("--poop"), + }, + .expected_vars = {0}, + .expected_rc = CLI_RC_BAD_ARGS, + }, + }; + for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { + vars = (struct vars){0}; + struct cli_ctx ctx = { + .opts = options, + .argc = cases[i].argc, + .argv = cases[i].argv, + }; + int rc = parse_long(&ctx); + asserteq(rc, cases[i].expected_rc); + asserteq(vars.i, cases[i].expected_vars.i); + asserteq(vars.u, cases[i].expected_vars.u); + if (cases[i].expected_vars.s) { + assertneq(vars.s, NULL); + asserteq(strcmp(vars.s, cases[i].expected_vars.s), 0); + } else { + asserteq(vars.s, NULL); + } + asserteq(vars.f, cases[i].expected_vars.f); + } + TEST_OUT +} +TEST_END + +TEST_BEGIN(test_parse_short) +{ + struct vars { + long i; + unsigned long u; + const char *s; + bool a; + bool b; + bool c; + } vars; + struct cli_opt options[] = { + { + .type = CLI_OT_INT, + .shor = 'i', + .value.i = &vars.i, + }, + { + .type = CLI_OT_FLAG, + .shor = 'a', + .value.f = &vars.a, + }, + { + .type = CLI_OT_FLAG, + .shor = 'b', + .value.f = &vars.b, + }, + { + .type = CLI_OT_FLAG, + .shor = 'c', + .value.f = &vars.c, + }, + { + .type = CLI_OT_UINT, + .shor = 'u', + .value.u = &vars.u, + }, + { + .type = CLI_OT_STRING, + .shor = 's', + .value.s = &vars.s, + }, + {0}, + }; + struct tcase { + int argc; + char *argv[2]; + struct vars expected_vars; + enum cli_rc expected_rc; + } cases[] = { + { + .argc = 2, + .argv = + { + MUTSTR("-i-2"), + MUTSTR("-b"), + }, + .expected_vars = + { + .i = -2, + .u = 0, + .s = NULL, + .a = false, + .b = false, + .c = false, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 1, + .argv = + { + MUTSTR("-cab"), + }, + .expected_vars = + { + .i = 0, + .u = 0, + .s = NULL, + .a = true, + .b = true, + .c = true, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 1, + .argv = + { + MUTSTR("-sab"), + }, + .expected_vars = + { + .i = 0, + .u = 0, + .s = "ab", + .a = false, + .b = false, + .c = false, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 2, + .argv = + { + MUTSTR("-abu"), + MUTSTR("24"), + }, + .expected_vars = + { + .i = 0, + .u = 24, + .s = NULL, + .a = true, + .b = true, + .c = false, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 2, + .argv = + { + MUTSTR("-ebu"), + MUTSTR("24"), + }, + .expected_vars = + { + .i = 0, + .u = 0, + .s = NULL, + .a = false, + .b = false, + .c = false, + }, + .expected_rc = CLI_RC_BAD_ARGS, + }, + }; + for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { + vars = (struct vars){0}; + struct cli_ctx ctx = { + .opts = options, + .argc = cases[i].argc, + .argv = cases[i].argv, + }; + int rc = parse_short(&ctx); + asserteq(rc, cases[i].expected_rc); + asserteq(vars.i, cases[i].expected_vars.i); + asserteq(vars.u, cases[i].expected_vars.u); + if (cases[i].expected_vars.s) { + assertneq(vars.s, NULL); + asserteq(strcmp(vars.s, cases[i].expected_vars.s), 0); + } else { + asserteq(vars.s, NULL); + } + asserteq(vars.a, cases[i].expected_vars.a); + asserteq(vars.b, cases[i].expected_vars.b); + asserteq(vars.c, cases[i].expected_vars.c); + } + TEST_OUT +} +TEST_END + +TEST_BEGIN(test_parse_options) +{ + struct vars { + long i; + unsigned long u; + const char *s; + bool a; + bool b; + bool c; + } vars; + struct cli_opt options[] = { + { + .type = CLI_OT_INT, + .lon = "signed", + .shor = 's', + .value.i = &vars.i, + }, + { + .type = CLI_OT_FLAG, + .lon = "flag-a", + .shor = 'a', + .value.f = &vars.a, + }, + { + .type = CLI_OT_FLAG, + .lon = "flag-b", + .shor = 'b', + .value.f = &vars.b, + }, + { + .type = CLI_OT_FLAG, + .lon = "flag-c", + .shor = 'c', + .value.f = &vars.c, + }, + { + .type = CLI_OT_UINT, + .lon = "unsigned", + .shor = 'u', + .value.u = &vars.u, + }, + { + .type = CLI_OT_STRING, + .lon = "string", + .shor = 'S', + .value.s = &vars.s, + }, + {0}, + }; + struct tcase { + int argc; + char *argv[8]; + struct vars expected_vars; + enum cli_rc expected_rc; + } cases[] = { + { + .argc = 5, + .argv = + { + MUTSTR("-s69"), + MUTSTR("--unsigned"), + MUTSTR("0xBEEF"), + MUTSTR("-Shore"), + MUTSTR("-bac"), + }, + .expected_vars = + { + .i = 69, + .u = 0xBEEF, + .s = "hore", + .a = true, + .b = true, + .c = true, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 6, + .argv = + { + MUTSTR("-c"), + MUTSTR("--unsigned=0777"), + MUTSTR("--signed"), + MUTSTR("-96"), + MUTSTR("--string=bebop"), + MUTSTR("--flag-b"), + }, + .expected_vars = + { + .i = -96, + .u = 0777, + .s = "bebop", + .a = false, + .b = true, + .c = true, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 1, + .argv = + { + MUTSTR("-aStronomical"), + }, + .expected_vars = + { + .i = 0, + .u = 0, + .s = "tronomical", + .a = true, + .b = false, + .c = false, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 4, + .argv = + { + MUTSTR("-cab"), + MUTSTR("--"), + MUTSTR("--string"), + MUTSTR("hello"), + }, + .expected_vars = + { + .i = 0, + .u = 0, + .s = NULL, + .a = true, + .b = true, + .c = true, + }, + .expected_rc = CLI_RC_OK, + }, + { + .argc = 2, + .argv = + { + MUTSTR("-cab"), + MUTSTR("--string"), + }, + .expected_vars = + { + .i = 0, + .u = 0, + .s = NULL, + .a = true, + .b = true, + .c = true, + }, + .expected_rc = CLI_RC_BAD_ARGS, + }, + { + .argc = 3, + .argv = + { + MUTSTR("-s86"), + MUTSTR("--beef"), + MUTSTR("steak"), + }, + .expected_vars = + { + .i = 86, + .u = 0, + .s = NULL, + .a = false, + .b = false, + .c = false, + }, + .expected_rc = CLI_RC_BAD_ARGS, + }, + }; + for (size_t i = 0; i < ARRAY_SIZE(cases); i++) { + vars = (struct vars){0}; + struct cli_ctx ctx = { + .opts = options, + .argc = cases[i].argc, + .argv = cases[i].argv, + }; + int rc = parse_options(&ctx); + asserteq(rc, cases[i].expected_rc); + asserteq(vars.i, cases[i].expected_vars.i); + asserteq(vars.u, cases[i].expected_vars.u); + if (cases[i].expected_vars.s) { + assertneq(vars.s, NULL); + asserteq(strcmp(vars.s, cases[i].expected_vars.s), 0); + } else { + asserteq(vars.s, NULL); + } + asserteq(vars.a, cases[i].expected_vars.a); + asserteq(vars.b, cases[i].expected_vars.b); + asserteq(vars.c, cases[i].expected_vars.c); + } + TEST_OUT +} +TEST_END + +RUN_TESTS(test_parse_long, test_parse_short, test_parse_options) |