aboutsummaryrefslogtreecommitdiff
path: root/cli/cli-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'cli/cli-test.c')
-rw-r--r--cli/cli-test.c524
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)