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