diff options
Diffstat (limited to 'posix/tst-getopt-cancel.c')
-rw-r--r-- | posix/tst-getopt-cancel.c | 284 |
1 files changed, 0 insertions, 284 deletions
diff --git a/posix/tst-getopt-cancel.c b/posix/tst-getopt-cancel.c deleted file mode 100644 index 594596a7b1..0000000000 --- a/posix/tst-getopt-cancel.c +++ /dev/null @@ -1,284 +0,0 @@ -/* Copyright (C) 2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* fprintf is a cancellation point, but getopt is not supposed to be a - cancellation point, even when it prints error messages. */ - -/* Note: getopt.h must be included first in this file, so we get the - GNU getopt rather than the POSIX one. */ -#include <getopt.h> - -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> - -#include <fcntl.h> -#include <pthread.h> -#include <unistd.h> - -#include <support/support.h> -#include <support/temp_file.h> -#include <support/xthread.h> - -static bool -check_stderr (bool expect_errmsg, FILE *stderr_trapped) -{ - static char *lineptr = 0; - static size_t linesz = 0; - - bool got_errmsg = false; - rewind (stderr_trapped); - while (getline (&lineptr, &linesz, stderr_trapped) > 0) - { - got_errmsg = true; - fputs (lineptr, stdout); - } - rewind (stderr_trapped); - ftruncate (fileno (stderr_trapped), 0); - return got_errmsg == expect_errmsg; -} - -struct test_short -{ - const char *label; - const char *opts; - const char *const argv[8]; - int argc; - bool expect_errmsg; -}; - -struct test_long -{ - const char *label; - const char *opts; - const struct option longopts[4]; - const char *const argv[8]; - int argc; - bool expect_errmsg; -}; - -#define DEFINE_TEST_DRIVER(test_type, getopt_call) \ - struct test_type##_tdata \ - { \ - pthread_mutex_t *sync; \ - const struct test_type *tcase; \ - bool ok; \ - }; \ - \ - static void * \ - test_type##_threadproc (void *data) \ - { \ - struct test_type##_tdata *tdata = data; \ - const struct test_type *tc = tdata->tcase; \ - \ - xpthread_mutex_lock (tdata->sync); \ - xpthread_mutex_unlock (tdata->sync); \ - \ - /* At this point, this thread has a cancellation pending. \ - We should still be able to get all the way through a getopt \ - loop without being cancelled. \ - Setting optind to 0 forces getopt to reinitialize itself. */ \ - optind = 0; \ - opterr = 1; \ - optopt = 0; \ - while (getopt_call != -1) \ - ; \ - tdata->ok = true; \ - \ - pthread_testcancel(); \ - return 0; \ - } \ - \ - static bool \ - do_##test_type (const struct test_type *tcase, FILE *stderr_trapped) \ - { \ - pthread_mutex_t sync; \ - struct test_type##_tdata tdata; \ - \ - printf("begin: %s\n", tcase->label); \ - \ - xpthread_mutex_init (&sync, 0); \ - xpthread_mutex_lock (&sync); \ - \ - tdata.sync = &sync; \ - tdata.tcase = tcase; \ - tdata.ok = false; \ - \ - pthread_t thr = xpthread_create (0, test_type##_threadproc, \ - (void *)&tdata); \ - xpthread_cancel (thr); \ - xpthread_mutex_unlock (&sync); \ - void *rv = xpthread_join (thr); \ - \ - xpthread_mutex_destroy (&sync); \ - \ - bool ok = true; \ - if (!check_stderr (tcase->expect_errmsg, stderr_trapped)) \ - { \ - ok = false; \ - printf("FAIL: %s: stderr not as expected\n", tcase->label); \ - } \ - if (!tdata.ok) \ - { \ - ok = false; \ - printf("FAIL: %s: did not complete loop\n", tcase->label); \ - } \ - if (rv != PTHREAD_CANCELED) \ - { \ - ok = false; \ - printf("FAIL: %s: thread was not cancelled\n", tcase->label); \ - } \ - if (ok) \ - printf ("pass: %s\n", tcase->label); \ - return ok; \ - } - -DEFINE_TEST_DRIVER (test_short, - getopt (tc->argc, (char *const *)tc->argv, tc->opts)) -DEFINE_TEST_DRIVER (test_long, - getopt_long (tc->argc, (char *const *)tc->argv, - tc->opts, tc->longopts, 0)) - -/* Caution: all option strings must begin with a '+' or '-' so that - getopt does not attempt to permute the argument vector (which is in - read-only memory). */ -const struct test_short tests_short[] = { - { "no errors", - "+ab:c", { "program", "-ac", "-b", "x", 0 }, 4, false }, - { "invalid option", - "+ab:c", { "program", "-d", 0 }, 2, true }, - { "missing argument", - "+ab:c", { "program", "-b", 0 }, 2, true }, - { 0 } -}; - -const struct test_long tests_long[] = { - { "no errors (long)", - "+ab:c", { { "alpha", no_argument, 0, 'a' }, - { "bravo", required_argument, 0, 'b' }, - { "charlie", no_argument, 0, 'c' }, - { 0 } }, - { "program", "-a", "--charlie", "--bravo=x", 0 }, 4, false }, - - { "invalid option (long)", - "+ab:c", { { "alpha", no_argument, 0, 'a' }, - { "bravo", required_argument, 0, 'b' }, - { "charlie", no_argument, 0, 'c' }, - { 0 } }, - { "program", "-a", "--charlie", "--dingo", 0 }, 4, true }, - - { "unwanted argument", - "+ab:c", { { "alpha", no_argument, 0, 'a' }, - { "bravo", required_argument, 0, 'b' }, - { "charlie", no_argument, 0, 'c' }, - { 0 } }, - { "program", "-a", "--charlie=dingo", "--bravo=x", 0 }, 4, true }, - - { "missing argument", - "+ab:c", { { "alpha", no_argument, 0, 'a' }, - { "bravo", required_argument, 0, 'b' }, - { "charlie", no_argument, 0, 'c' }, - { 0 } }, - { "program", "-a", "--charlie", "--bravo", 0 }, 4, true }, - - { "ambiguous options", - "+uvw", { { "veni", no_argument, 0, 'u' }, - { "vedi", no_argument, 0, 'v' }, - { "veci", no_argument, 0, 'w' } }, - { "program", "--ve", 0 }, 2, true }, - - { "no errors (long W)", - "+ab:cW;", { { "alpha", no_argument, 0, 'a' }, - { "bravo", required_argument, 0, 'b' }, - { "charlie", no_argument, 0, 'c' }, - { 0 } }, - { "program", "-a", "-W", "charlie", "-W", "bravo=x", 0 }, 6, false }, - - { "missing argument (W itself)", - "+ab:cW;", { { "alpha", no_argument, 0, 'a' }, - { "bravo", required_argument, 0, 'b' }, - { "charlie", no_argument, 0, 'c' }, - { 0 } }, - { "program", "-a", "-W", "charlie", "-W", 0 }, 5, true }, - - { "missing argument (W longopt)", - "+ab:cW;", { { "alpha", no_argument, 0, 'a' }, - { "bravo", required_argument, 0, 'b' }, - { "charlie", no_argument, 0, 'c' }, - { 0 } }, - { "program", "-a", "-W", "charlie", "-W", "bravo", 0 }, 6, true }, - - { "unwanted argument (W longopt)", - "+ab:cW;", { { "alpha", no_argument, 0, 'a' }, - { "bravo", required_argument, 0, 'b' }, - { "charlie", no_argument, 0, 'c' }, - { 0 } }, - { "program", "-a", "-W", "charlie=dingo", "-W", "bravo=x", 0 }, 6, true }, - - { "ambiguous options (W)", - "+uvwW;", { { "veni", no_argument, 0, 'u' }, - { "vedi", no_argument, 0, 'v' }, - { "veci", no_argument, 0, 'w' } }, - { "program", "-W", "ve", 0 }, 3, true }, - - { 0 } -}; - -static int -do_test (void) -{ - int stderr_trap = create_temp_file ("stderr", 0); - if (stderr_trap < 0) - { - perror ("create_temp_file"); - return 1; - } - FILE *stderr_trapped = fdopen(stderr_trap, "r+"); - if (!stderr_trapped) - { - perror ("fdopen"); - return 1; - } - int old_stderr = dup (fileno (stderr)); - if (old_stderr < 0) - { - perror ("dup"); - return 1; - } - if (dup2 (stderr_trap, 2) < 0) - { - perror ("dup2"); - return 1; - } - rewind (stderr); - - bool success = true; - - for (const struct test_short *tcase = tests_short; tcase->label; tcase++) - success = do_test_short (tcase, stderr_trapped) && success; - - for (const struct test_long *tcase = tests_long; tcase->label; tcase++) - success = do_test_long (tcase, stderr_trapped) && success; - - dup2 (old_stderr, 2); - close (old_stderr); - fclose (stderr_trapped); - - return success ? 0 : 1; -} - -#include <support/test-driver.c> |