getopt.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. #include <common.h>
  9. #include <getopt.h>
  10. #include <test/lib.h>
  11. #include <test/test.h>
  12. #include <test/ut.h>
  13. static int do_test_getopt(struct unit_test_state *uts, int line,
  14. struct getopt_state *gs, const char *optstring,
  15. int args, char *argv[], int expected_count,
  16. int expected[])
  17. {
  18. int opt;
  19. getopt_init_state(gs);
  20. for (int i = 0; i < expected_count; i++) {
  21. opt = getopt_silent(gs, args, argv, optstring);
  22. if (expected[i] != opt) {
  23. /*
  24. * Fudge the line number so we can tell which test
  25. * failed
  26. */
  27. ut_failf(uts, __FILE__, line, __func__,
  28. "expected[i] == getopt()",
  29. "Expected '%c' (%d) with i=%d, got '%c' (%d)",
  30. expected[i], expected[i], i, opt, opt);
  31. return CMD_RET_FAILURE;
  32. }
  33. }
  34. opt = getopt_silent(gs, args, argv, optstring);
  35. if (opt != -1) {
  36. ut_failf(uts, __FILE__, line, __func__,
  37. "getopt() != -1",
  38. "Expected -1, got '%c' (%d)", opt, opt);
  39. return CMD_RET_FAILURE;
  40. }
  41. return 0;
  42. }
  43. #define test_getopt(optstring, argv, expected) do { \
  44. int ret = do_test_getopt(uts, __LINE__, &gs, optstring, \
  45. ARRAY_SIZE(argv) - 1, argv, \
  46. ARRAY_SIZE(expected), expected); \
  47. if (ret) \
  48. return ret; \
  49. } while (0)
  50. static int lib_test_getopt(struct unit_test_state *uts)
  51. {
  52. struct getopt_state gs;
  53. /* Happy path */
  54. test_getopt("ab:c",
  55. ((char *[]){ "program", "-cb", "x", "-a", "foo", 0 }),
  56. ((int []){ 'c', 'b', 'a' }));
  57. ut_asserteq(4, gs.index);
  58. /* Make sure we pick up the optional argument */
  59. test_getopt("a::b:c",
  60. ((char *[]){ "program", "-cbx", "-a", "foo", 0 }),
  61. ((int []){ 'c', 'b', 'a' }));
  62. ut_asserteq(4, gs.index);
  63. /* Test required arguments */
  64. test_getopt("a:b", ((char *[]){ "program", "-a", 0 }),
  65. ((int []){ ':' }));
  66. ut_asserteq('a', gs.opt);
  67. test_getopt("a:b", ((char *[]){ "program", "-b", "-a", 0 }),
  68. ((int []){ 'b', ':' }));
  69. ut_asserteq('a', gs.opt);
  70. /* Test invalid arguments */
  71. test_getopt("ab:c", ((char *[]){ "program", "-d", 0 }),
  72. ((int []){ '?' }));
  73. ut_asserteq('d', gs.opt);
  74. /* Test arg */
  75. test_getopt("a::b:c",
  76. ((char *[]){ "program", "-a", 0 }),
  77. ((int []){ 'a' }));
  78. ut_asserteq(2, gs.index);
  79. ut_assertnull(gs.arg);
  80. test_getopt("a::b:c",
  81. ((char *[]){ "program", "-afoo", 0 }),
  82. ((int []){ 'a' }));
  83. ut_asserteq(2, gs.index);
  84. ut_assertnonnull(gs.arg);
  85. ut_asserteq_str("foo", gs.arg);
  86. test_getopt("a::b:c",
  87. ((char *[]){ "program", "-a", "foo", 0 }),
  88. ((int []){ 'a' }));
  89. ut_asserteq(3, gs.index);
  90. ut_assertnonnull(gs.arg);
  91. ut_asserteq_str("foo", gs.arg);
  92. test_getopt("a::b:c",
  93. ((char *[]){ "program", "-bfoo", 0 }),
  94. ((int []){ 'b' }));
  95. ut_asserteq(2, gs.index);
  96. ut_assertnonnull(gs.arg);
  97. ut_asserteq_str("foo", gs.arg);
  98. test_getopt("a::b:c",
  99. ((char *[]){ "program", "-b", "foo", 0 }),
  100. ((int []){ 'b' }));
  101. ut_asserteq(3, gs.index);
  102. ut_assertnonnull(gs.arg);
  103. ut_asserteq_str("foo", gs.arg);
  104. return 0;
  105. }
  106. LIB_TEST(lib_test_getopt, 0);