Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com> * * Portions of these tests were inspired by glibc's posix/bug-getopt1.c and * posix/tst-getopt-cancel.c */ #include <getopt.h> #include <test/lib.h> #include <test/test.h> #include <test/ut.h> static int do_test_getopt(struct unit_test_state *uts, int line, struct getopt_state *gs, const char *optstring, int args, char *argv[], int expected_count, int expected[]) { int opt; getopt_init_state(gs); for (int i = 0; i < expected_count; i++) { opt = getopt_silent(gs, args, argv, optstring); if (expected[i] != opt) { /* * Fudge the line number so we can tell which test * failed */ ut_failf(uts, __FILE__, line, __func__, "expected[i] == getopt()", "Expected '%c' (%d) with i=%d, got '%c' (%d)", expected[i], expected[i], i, opt, opt); return CMD_RET_FAILURE; } } opt = getopt_silent(gs, args, argv, optstring); if (opt != -1) { ut_failf(uts, __FILE__, line, __func__, "getopt() != -1", "Expected -1, got '%c' (%d)", opt, opt); return CMD_RET_FAILURE; } return 0; } #define test_getopt(optstring, argv, expected) do { \ int ret = do_test_getopt(uts, __LINE__, &gs, optstring, \ ARRAY_SIZE(argv) - 1, argv, \ ARRAY_SIZE(expected), expected); \ if (ret) \ return ret; \ } while (0) static int lib_test_getopt(struct unit_test_state *uts) { struct getopt_state gs; /* Happy path */ test_getopt("ab:c", ((char *[]){ "program", "-cb", "x", "-a", "foo", 0 }), ((int []){ 'c', 'b', 'a' })); ut_asserteq(4, gs.index); /* Make sure we pick up the optional argument */ test_getopt("a::b:c", ((char *[]){ "program", "-cbx", "-a", "foo", 0 }), ((int []){ 'c', 'b', 'a' })); ut_asserteq(4, gs.index); /* Test required arguments */ test_getopt("a:b", ((char *[]){ "program", "-a", 0 }), ((int []){ ':' })); ut_asserteq('a', gs.opt); test_getopt("a:b", ((char *[]){ "program", "-b", "-a", 0 }), ((int []){ 'b', ':' })); ut_asserteq('a', gs.opt); /* Test invalid arguments */ test_getopt("ab:c", ((char *[]){ "program", "-d", 0 }), ((int []){ '?' })); ut_asserteq('d', gs.opt); /* Test arg */ test_getopt("a::b:c", ((char *[]){ "program", "-a", 0 }), ((int []){ 'a' })); ut_asserteq(2, gs.index); ut_assertnull(gs.arg); test_getopt("a::b:c", ((char *[]){ "program", "-afoo", 0 }), ((int []){ 'a' })); ut_asserteq(2, gs.index); ut_assertnonnull(gs.arg); ut_asserteq_str("foo", gs.arg); test_getopt("a::b:c", ((char *[]){ "program", "-a", "foo", 0 }), ((int []){ 'a' })); ut_asserteq(3, gs.index); ut_assertnonnull(gs.arg); ut_asserteq_str("foo", gs.arg); test_getopt("a::b:c", ((char *[]){ "program", "-bfoo", 0 }), ((int []){ 'b' })); ut_asserteq(2, gs.index); ut_assertnonnull(gs.arg); ut_asserteq_str("foo", gs.arg); test_getopt("a::b:c", ((char *[]){ "program", "-b", "foo", 0 }), ((int []){ 'b' })); ut_asserteq(3, gs.index); ut_assertnonnull(gs.arg); ut_asserteq_str("foo", gs.arg); return 0; } LIB_TEST(lib_test_getopt, 0); |