From bd5969fc876a10b18613302db7087ef3c40f18e1 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 7 Mar 2024 17:28:00 -0500 Subject: lib: Add mlibc Signed-off-by: Ian Moffett --- lib/mlibc/tests/glibc/getopt.c | 288 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 lib/mlibc/tests/glibc/getopt.c (limited to 'lib/mlibc/tests/glibc/getopt.c') diff --git a/lib/mlibc/tests/glibc/getopt.c b/lib/mlibc/tests/glibc/getopt.c new file mode 100644 index 0000000..a0e27bb --- /dev/null +++ b/lib/mlibc/tests/glibc/getopt.c @@ -0,0 +1,288 @@ +#include +#include +#include +#include +#include +#include +#include + +#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) +#define dump(x) fprintf(stderr, "getopt c '%c' (%d), optind %d ('%s'), optarg '%s', optopt '%c' (%d)\n", \ + (x), (x), optind, (size_t)optind >= COUNT_OF(test_argv) ? "out of range" : test_argv[optind], optarg, optopt, optopt); + +void test1() { + const char *shortopts = "b:cdef"; + + const struct option longopts[] = { + {"foo", required_argument, NULL, 'f'}, + {NULL, no_argument, NULL, 0} + }; + + int test_argc = 7; + + char *test_argv[] = { + "dummy", + "--foo", + "abc", + "-b", + "abc", + "abc", + "abc" + }; + + optind = 0; + int c = getopt_long(test_argc, test_argv, shortopts, longopts, NULL); + dump(c) + assert(c == 'f'); + + c = getopt_long(test_argc, test_argv, shortopts, longopts, NULL); + dump(c) + assert(optarg && !strcmp(optarg, "abc")); + assert(c == 'b'); + + c = getopt_long(test_argc, test_argv, shortopts, longopts, NULL); + dump(c); + assert(c == -1); + assert(optarg == NULL); + + // we have 2 non-option arguments + assert((optind + 2) == test_argc); +} + +void test2() { + const struct option longopts[] = { + {"foo", required_argument, NULL, 'f'}, + {NULL, no_argument, NULL, 0} + }; + + char *test_argv[] = { + "dummy", + "-c", + }; + + fputs("Situation: we pass a non-existant short option in argv\n", stderr); + + optind = 0; + int c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:", longopts, NULL); + // Exprected result: return '?', optopt is set to the offender + assert(c == '?'); + assert(optopt == 'c'); + + fputs("Situation: we pass a non-existant short option in argv, while passing a leading colon in optstring\n", stderr); + optind = 0; + + c = getopt_long(COUNT_OF(test_argv), test_argv, ":ab:", longopts, NULL); + // Exprected result: return '?', optopt is set to the offender + assert(c == '?'); + assert(optopt == 'c'); + + fputs("Situation: we omit the required arg to a short option\n", stderr); + optind = 0; + + c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:c:", longopts, NULL); + // Exprected result: return '?', optopt is set to the offender + assert(c == '?'); + assert(optopt == 'c'); + + fputs("Situation: we omit the required arg to a short option, while passing a leading colon in optstring\n", stderr); + optind = 0; + + c = getopt_long(COUNT_OF(test_argv), test_argv, ":ab:c:", longopts, NULL); + // Exprected result: return ':', optopt is set to the offender + assert(c == ':'); + assert(optopt == 'c'); +} + +void test3() { + const struct option longopts[] = { + {"foo", required_argument, NULL, 'f'}, + {NULL, no_argument, NULL, 0} + }; + + char *test_argv[] = { + "dummy", + "-cmanagarm", + }; + + fputs("Situation: we pass a concatenated argument to a short option\n", stderr); + + optind = 0; + int c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:c:", longopts, NULL); + dump(c); + // Exprected result: + assert(c == 'c'); + assert(!strcmp(optarg, "managarm")); +} + +void test4() { + const struct option longopts[] = { + {"foo", required_argument, NULL, 'f'}, + {NULL, no_argument, NULL, 0} + }; + + char *test_argv[] = { + "dummy", + "-acmanagarm", + }; + + fputs("Situation: we pass concatenated short options to getopt\n", stderr); + + optind = 0; + int c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:c:", longopts, NULL); + assert(c == 'a'); + + c = getopt_long(COUNT_OF(test_argv), test_argv, "ab:c:", longopts, NULL); + // Exprected result: + assert(c == 'c'); + assert(!strcmp(optarg, "managarm")); +} + +void test5() { + const struct option longopts[] = { + {"foo", required_argument, NULL, 'f'}, + {NULL, no_argument, NULL, 0} + }; + + char *test_argv[] = { + "su", + "-", + "managarm", + 0 + }; + + int test_argc = 3; + + fputs("Situation: testing `su - managarm`\n", stderr); + + optind = 0; + int c = getopt_long(test_argc, test_argv, "ab:", longopts, NULL); + dump(c); + assert(c == -1); + + if (optind < test_argc && !strcmp(test_argv[optind], "-")) { + ++optind; + } + + assert(optind < test_argc); + assert(!strcmp(test_argv[optind++], "managarm")); + assert(optind == test_argc); +} + +void test6() { + char *test_argv[] = { + "telescope", + "gemini://electrode.codes", + "-S", + 0 + }; + + int test_argc = 3; + optind = 0; + + const struct option longopts[] = { + {"colors", no_argument, NULL, 'C'}, + {"colours", no_argument, NULL, 'C'}, + {"help", no_argument, NULL, 'h'}, + {"safe", no_argument, NULL, 'S'}, + {"version", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0}, + }; + + int c = getopt_long(test_argc, test_argv, "Cc:hnST:v", longopts, NULL); + dump(c); + assert(c == 'S'); + assert(optind == 3); + assert(!optarg); +} + +void test7() { + int c; + + static const struct option options[] = { + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + {} + }; + const char *command; + + char *test_argv[] = { + "udevadm", + "hwdb", + "--update", + 0 + }; + + int test_argc = 3; + setenv("POSIXLY_CORRECT", "1", 1); + optind = 0; + + while ((c = getopt_long(test_argc, test_argv, "+dhV", options, NULL)) >= 0) { + switch (c) { + case 'd': + break; + case 'h': + break; + case 'V': + break; + default: + break; + } + } + + dump(c); + command = test_argv[optind]; + assert(command); + assert(!strcmp(command, "hwdb")); +} + +void test8() { + const char *shortopts = "b:cde"; + + int foo = false; + int bar = false; + + const struct option longopts[] = { + {"foo", required_argument, &foo, 'x'}, + {"bar", required_argument, &bar, 'y'}, + {NULL, no_argument, NULL, 0} + }; + + int test_argc = 6; + + char *test_argv[] = { + "dummy", + "-foo", + "abc", + "-bar=def", + "ghi", + "jkl" + }; + + #ifdef __GLIBC__ + optind = 0; + #else + optreset = 1; + #endif + optopt = 0; + int c = getopt_long_only(test_argc, test_argv, shortopts, longopts, NULL); + dump(c); + assert(foo && !c); + assert(optind == 3); + + c = getopt_long_only(test_argc, test_argv, shortopts, longopts, NULL); + dump(c); + assert(bar && !c); + assert(optind == 4); +} + +int main() { + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); + test8(); +} -- cgit v1.2.3