From 3c8bb39bef81eb88a2aa9bdfd8af00ca151b86fd Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Wed, 2 Dec 2009 15:48:08 -0700 Subject: [PATCH] test-getopt: test stderr behavior Portions of this commit are commented out because they tickle glibc bugs. For a real-life example of the bug: $ env -ua -: env: invalid option -- : Try `env --help' for more information. $ env -: env: invalid option -- : Try `env --help' for more information. $ env -+ env: invalid option -- + Try `env --help' for more information. $ env -ua -+ Try `env --help' for more information. Notice that when -+ is not given as the first argument, the error message is mistakenly suppressed. * modules/getopt-posix-tests (Depends-on): Add dup2. * tests/test-getopt.c (ASSERT): Avoid stderr. (main): Move stderr to a temporary file. * tests/test-getopt.h (getopt_loop): No longer manipulate opterr. Instead, add parameter to inform caller if output occurred. (test_getopt): Adjust all tests to expect silence, and add new tests of leading ":". * doc/glibc-functions/getopt_long.texi (getopt_long): Document glibc shortcomings with leading "-:" or "+:" in optstring. * doc/glibc-functions/getopt_long_only.texi (getopt_long_only): Likewise. * doc/posix-functions/getopt.texi (getopt): Likewise. Signed-off-by: Eric Blake --- ChangeLog | 14 ++ doc/glibc-functions/getopt_long.texi | 3 + doc/glibc-functions/getopt_long_only.texi | 3 + doc/posix-functions/getopt.texi | 3 + modules/getopt-posix-tests | 1 + tests/test-getopt.c | 29 ++- tests/test-getopt.h | 387 ++++++++++++++++++++++++++++-- 7 files changed, 415 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index b73961aa7..73b4b57ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2009-12-22 Eric Blake + test-getopt: test stderr behavior + * modules/getopt-posix-tests (Depends-on): Add dup2. + * tests/test-getopt.c (ASSERT): Avoid stderr. + (main): Move stderr to a temporary file. + * tests/test-getopt.h (getopt_loop): No longer manipulate opterr. + Instead, add parameter to inform caller if output occurred. + (test_getopt): Adjust all existing tests to expect silence, and + add new tests of leading ":". + * doc/glibc-functions/getopt_long.texi (getopt_long): Document + glibc shortcomings with leading "-:" or "+:" in optstring. + * doc/glibc-functions/getopt_long_only.texi (getopt_long_only): + Likewise. + * doc/posix-functions/getopt.texi (getopt): Likewise. + test-getopt: enhance test * m4/getopt.m4 (gl_GETOPT_CHECK_HEADERS): Require that getopt_long supports optind=0. diff --git a/doc/glibc-functions/getopt_long.texi b/doc/glibc-functions/getopt_long.texi index a0f8cf4cb..0472514b5 100644 --- a/doc/glibc-functions/getopt_long.texi +++ b/doc/glibc-functions/getopt_long.texi @@ -33,4 +33,7 @@ Portability problems not fixed by Gnulib: The glibc extension of using @samp{W;} in the optstring argument to allow @code{-W foo} to behave synonymously with @code{--foo} is not very reliable, even in glibc. +@item +Mixing a leading @samp{-} or @samp{+} with a leading @samp{:} in the +optstring argument has inconsistent effects across platforms. @end itemize diff --git a/doc/glibc-functions/getopt_long_only.texi b/doc/glibc-functions/getopt_long_only.texi index fcda30073..13edfb42e 100644 --- a/doc/glibc-functions/getopt_long_only.texi +++ b/doc/glibc-functions/getopt_long_only.texi @@ -38,4 +38,7 @@ very reliable. Some implementations return success instead of reporting an ambiguity if user's option is a prefix of two long options with the same flag: FreeBSD. +@item +Mixing a leading @samp{-} or @samp{+} with a leading @samp{:} in the +optstring argument has inconsistent effects across platforms. @end itemize diff --git a/doc/posix-functions/getopt.texi b/doc/posix-functions/getopt.texi index 85f5289f1..822dbb3ea 100644 --- a/doc/posix-functions/getopt.texi +++ b/doc/posix-functions/getopt.texi @@ -57,4 +57,7 @@ including re-checking for @env{POSIXLY_CORRECT}, by setting @code{optind} to 0. Other implementations provide @code{optreset}, causing a reset by setting it non-zero, although it does not necessarily re-read @env{POSIXLY_CORRECT}. +@item +Mixing a leading @samp{-} or @samp{+} with a leading @samp{:} in the +optstring argument has inconsistent effects across platforms. @end itemize diff --git a/modules/getopt-posix-tests b/modules/getopt-posix-tests index be828cfee..b2e372753 100644 --- a/modules/getopt-posix-tests +++ b/modules/getopt-posix-tests @@ -4,6 +4,7 @@ tests/test-getopt.h tests/test-getopt_long.h Depends-on: +dup2 setenv stdbool unistd diff --git a/tests/test-getopt.c b/tests/test-getopt.c index 591cf0b45..6811a0205 100644 --- a/tests/test-getopt.c +++ b/tests/test-getopt.c @@ -18,6 +18,13 @@ #include +/* None of the files accessed by this test are large, so disable the + ftell link warning if we are not using the gnulib ftell module. */ +#if !GNULIB_FTELL +# undef GL_LINK_WARNING +# define GL_LINK_WARNING(ignored) ((void) 0) +#endif + #if GNULIB_GETOPT_GNU # include #endif @@ -27,13 +34,20 @@ #include #include +/* This test intentionally remaps stderr. So, we arrange to have fd 10 + (outside the range of interesting fd's during the test) set up to + duplicate the original stderr. */ + +#define BACKUP_STDERR_FILENO 10 +static FILE *myerr; + #define ASSERT(expr) \ do \ { \ if (!(expr)) \ { \ - fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ - fflush (stderr); \ + fprintf (myerr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (myerr); \ abort (); \ } \ } \ @@ -47,6 +61,14 @@ int main (void) { + /* This test validates that stderr is used correctly, so move the + original into fd 10. */ + if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO + || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL) + return 2; + + ASSERT (freopen ("test-getopt.tmp", "w", stderr) == stderr); + /* These default values are required by POSIX. */ ASSERT (optind == 1); ASSERT (opterr != 0); @@ -66,5 +88,8 @@ main (void) test_getopt_long_only (); #endif + ASSERT (fclose (stderr) == 0); + ASSERT (remove ("test-getopt.tmp") == 0); + return 0; } diff --git a/tests/test-getopt.h b/tests/test-getopt.h index 400bc279e..ca8872f6a 100644 --- a/tests/test-getopt.h +++ b/tests/test-getopt.h @@ -35,11 +35,11 @@ getopt_loop (int argc, const char **argv, int *a_seen, int *b_seen, const char **p_value, const char **q_value, int *non_options_count, const char **non_options, - int *unrecognized) + int *unrecognized, bool *message_issued) { int c; + int pos = ftell (stderr); - opterr = 0; while ((c = getopt (argc, (char **) argv, options)) != -1) { switch (c) @@ -61,6 +61,12 @@ getopt_loop (int argc, const char **argv, ASSERT (options[0] == '-'); non_options[(*non_options_count)++] = optarg; break; + case ':': + /* Must only happen with option ':' at the beginning. */ + ASSERT (options[0] == ':' + || ((options[0] == '-' || options[0] == '+') + && options[1] == ':')); + /* fall through */ case '?': *unrecognized = optopt; break; @@ -69,6 +75,8 @@ getopt_loop (int argc, const char **argv, break; } } + + *message_issued = pos < ftell (stderr); } static void @@ -94,6 +102,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -103,9 +112,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "ab", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value == NULL); @@ -113,6 +123,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 2); + ASSERT (!output); } for (start = OPTIND_MIN; start <= 1; start++) { @@ -123,6 +134,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -133,9 +145,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "ab", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 1); ASSERT (b_seen == 1); ASSERT (p_value == NULL); @@ -143,6 +156,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 3); + ASSERT (!output); } for (start = OPTIND_MIN; start <= 1; start++) { @@ -153,6 +167,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -162,9 +177,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "ab", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 1); ASSERT (b_seen == 1); ASSERT (p_value == NULL); @@ -172,6 +188,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 2); + ASSERT (!output); } for (start = OPTIND_MIN; start <= 1; start++) { @@ -182,6 +199,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -192,9 +210,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "ab", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 2); ASSERT (b_seen == 1); ASSERT (p_value == NULL); @@ -202,6 +221,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 3); + ASSERT (!output); } /* Test processing of options with arguments. */ @@ -214,6 +234,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -222,9 +243,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "p:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); @@ -232,6 +254,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 2); + ASSERT (!output); } for (start = OPTIND_MIN; start <= 1; start++) { @@ -242,6 +265,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -251,9 +275,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "p:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); @@ -261,6 +286,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 3); + ASSERT (!output); } for (start = OPTIND_MIN; start <= 1; start++) { @@ -271,6 +297,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -282,9 +309,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "abp:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 1); ASSERT (b_seen == 1); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); @@ -292,6 +320,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 5); + ASSERT (!output); } #if GNULIB_GETOPT_GNU @@ -305,6 +334,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -313,9 +343,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "p::q::", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); @@ -323,6 +354,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 2); + ASSERT (!output); } for (start = OPTIND_MIN; start <= 1; start++) { @@ -333,6 +365,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -342,9 +375,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "p::q::", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value == NULL); @@ -352,6 +386,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 2); + ASSERT (!output); } for (start = OPTIND_MIN; start <= 1; start++) { @@ -362,6 +397,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -371,9 +407,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "abp::q::", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value == NULL); @@ -381,10 +418,46 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 3); + ASSERT (!output); } #endif - /* Check that invalid options are recognized. */ + /* Check that invalid options are recognized; and that both opterr + and leading ':' can silence output. */ + for (start = OPTIND_MIN; start <= 1; start++) + { + int a_seen = 0; + int b_seen = 0; + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + bool output; + int argc = 0; + const char *argv[10]; + + argv[argc++] = "program"; + argv[argc++] = "-p"; + argv[argc++] = "foo"; + argv[argc++] = "-x"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + opterr = 42; + getopt_loop (argc, argv, "abp:q:", + &a_seen, &b_seen, &p_value, &q_value, + &non_options_count, non_options, &unrecognized, &output); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 'x'); + ASSERT (optind == 5); + ASSERT (output); + } for (start = OPTIND_MIN; start <= 1; start++) { int a_seen = 0; @@ -394,6 +467,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -405,9 +479,44 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 0; getopt_loop (argc, argv, "abp:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 'x'); + ASSERT (optind == 5); + ASSERT (!output); + } + for (start = OPTIND_MIN; start <= 1; start++) + { + int a_seen = 0; + int b_seen = 0; + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + bool output; + int argc = 0; + const char *argv[10]; + + argv[argc++] = "program"; + argv[argc++] = "-p"; + argv[argc++] = "foo"; + argv[argc++] = "-x"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + opterr = 1; + getopt_loop (argc, argv, ":abp:q:", + &a_seen, &b_seen, &p_value, &q_value, + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); @@ -415,6 +524,201 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 'x'); ASSERT (optind == 5); + ASSERT (!output); + } + for (start = OPTIND_MIN; start <= 1; start++) + { + int a_seen = 0; + int b_seen = 0; + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + bool output; + int argc = 0; + const char *argv[10]; + + argv[argc++] = "program"; + argv[argc++] = "-p"; + argv[argc++] = "foo"; + argv[argc++] = "-:"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + opterr = 42; + getopt_loop (argc, argv, "abp:q:", + &a_seen, &b_seen, &p_value, &q_value, + &non_options_count, non_options, &unrecognized, &output); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == ':'); + ASSERT (optind == 5); + ASSERT (output); + } + for (start = OPTIND_MIN; start <= 1; start++) + { + int a_seen = 0; + int b_seen = 0; + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + bool output; + int argc = 0; + const char *argv[10]; + + argv[argc++] = "program"; + argv[argc++] = "-p"; + argv[argc++] = "foo"; + argv[argc++] = "-:"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + opterr = 0; + getopt_loop (argc, argv, "abp:q:", + &a_seen, &b_seen, &p_value, &q_value, + &non_options_count, non_options, &unrecognized, &output); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == ':'); + ASSERT (optind == 5); + ASSERT (!output); + } + for (start = OPTIND_MIN; start <= 1; start++) + { + int a_seen = 0; + int b_seen = 0; + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + bool output; + int argc = 0; + const char *argv[10]; + + argv[argc++] = "program"; + argv[argc++] = "-p"; + argv[argc++] = "foo"; + argv[argc++] = "-:"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + opterr = 1; + getopt_loop (argc, argv, ":abp:q:", + &a_seen, &b_seen, &p_value, &q_value, + &non_options_count, non_options, &unrecognized, &output); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == ':'); + ASSERT (optind == 5); + ASSERT (!output); + } + + /* Check for missing argument behavior. */ + for (start = OPTIND_MIN; start <= 1; start++) + { + int a_seen = 0; + int b_seen = 0; + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + bool output; + int argc = 0; + const char *argv[10]; + + argv[argc++] = "program"; + argv[argc++] = "-ap"; + argv[argc] = NULL; + optind = start; + opterr = 1; + getopt_loop (argc, argv, "abp:q:", + &a_seen, &b_seen, &p_value, &q_value, + &non_options_count, non_options, &unrecognized, &output); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 'p'); + ASSERT (optind == 2); + ASSERT (output); + } + for (start = OPTIND_MIN; start <= 1; start++) + { + int a_seen = 0; + int b_seen = 0; + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + bool output; + int argc = 0; + const char *argv[10]; + + argv[argc++] = "program"; + argv[argc++] = "-ap"; + argv[argc] = NULL; + optind = start; + opterr = 0; + getopt_loop (argc, argv, "abp:q:", + &a_seen, &b_seen, &p_value, &q_value, + &non_options_count, non_options, &unrecognized, &output); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 'p'); + ASSERT (optind == 2); + ASSERT (!output); + } + for (start = OPTIND_MIN; start <= 1; start++) + { + int a_seen = 0; + int b_seen = 0; + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + bool output; + int argc = 0; + const char *argv[10]; + + argv[argc++] = "program"; + argv[argc++] = "-ap"; + argv[argc] = NULL; + optind = start; + opterr = 1; + getopt_loop (argc, argv, ":abp:q:", + &a_seen, &b_seen, &p_value, &q_value, + &non_options_count, non_options, &unrecognized, &output); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 'p'); + ASSERT (optind == 2); + ASSERT (!output); } /* Check that by default, non-options arguments are moved to the end. */ @@ -427,6 +731,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -439,9 +744,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "abp:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); if (posixly) { ASSERT (strcmp (argv[0], "program") == 0); @@ -459,6 +765,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 1); + ASSERT (!output); } else { @@ -477,6 +784,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 4); + ASSERT (!output); } } @@ -490,6 +798,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[20]; @@ -507,9 +816,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "abp:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); if (posixly) { ASSERT (strcmp (argv[0], "program") == 0); @@ -532,6 +842,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 1); + ASSERT (!output); } else { @@ -555,6 +866,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 5); + ASSERT (!output); } } @@ -569,6 +881,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -581,9 +894,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "-abp:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "donald") == 0); ASSERT (strcmp (argv[2], "-p") == 0); @@ -602,6 +916,7 @@ test_getopt (void) ASSERT (strcmp (non_options[2], "bar") == 0); ASSERT (unrecognized == 0); ASSERT (optind == 7); + ASSERT (!output); } /* Check that '--' ends the argument processing. */ @@ -614,6 +929,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[20]; @@ -631,9 +947,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "-abp:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "donald") == 0); ASSERT (strcmp (argv[2], "-p") == 0); @@ -651,6 +968,7 @@ test_getopt (void) ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0); ASSERT (q_value == NULL); + ASSERT (!output); if (non_options_count == 2) { /* glibc behaviour. */ @@ -687,6 +1005,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -699,9 +1018,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "abp:q:-", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); if (posixly) { ASSERT (strcmp (argv[0], "program") == 0); @@ -719,6 +1039,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 1); + ASSERT (!output); } else { @@ -737,6 +1058,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 4); + ASSERT (!output); } } @@ -751,6 +1073,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -763,9 +1086,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "+abp:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "donald") == 0); ASSERT (strcmp (argv[2], "-p") == 0); @@ -781,6 +1105,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 1); + ASSERT (!output); } for (start = OPTIND_MIN; start <= 1; start++) { @@ -791,6 +1116,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -798,9 +1124,13 @@ test_getopt (void) argv[argc++] = "-+"; argv[argc] = NULL; optind = start; + /* Suppress output, since glibc is inconsistent on whether this + prints a message: + http://sources.redhat.com/bugzilla/show_bug.cgi?id=11039 */ + opterr = 0; getopt_loop (argc, argv, "+abp:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value == NULL); @@ -808,6 +1138,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == '+'); ASSERT (optind == 2); + ASSERT (!output); } /* Check that '--' ends the argument processing. */ @@ -820,6 +1151,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[20]; @@ -837,9 +1169,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "+abp:q:", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "donald") == 0); ASSERT (strcmp (argv[2], "-p") == 0); @@ -860,6 +1193,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind = 1); + ASSERT (!output); } /* Check that the '+' flag has to come first. */ @@ -872,6 +1206,7 @@ test_getopt (void) int non_options_count = 0; const char *non_options[10]; int unrecognized = 0; + bool output; int argc = 0; const char *argv[10]; @@ -884,9 +1219,10 @@ test_getopt (void) argv[argc++] = "bar"; argv[argc] = NULL; optind = start; + opterr = 1; getopt_loop (argc, argv, "abp:q:+", &a_seen, &b_seen, &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &non_options_count, non_options, &unrecognized, &output); if (posixly) { ASSERT (strcmp (argv[0], "program") == 0); @@ -904,6 +1240,7 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 1); + ASSERT (!output); } else { @@ -922,6 +1259,10 @@ test_getopt (void) ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); ASSERT (optind == 4); + ASSERT (!output); } } + + /* No tests of "-:..." or "+:...", due to glibc bug: + http://sources.redhat.com/bugzilla/show_bug.cgi?id=11039 */ } -- 2.11.0