summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschwarze <>2020-03-23 03:01:21 +0000
committerschwarze <>2020-03-23 03:01:21 +0000
commited759aa6a877b98293e7fa74ea83ad183ea1157d (patch)
treed69c1a3c72fe892dcd93216b0b88609a95810c0a
parentafbeb5d666df4224373ad3c47cef95d0c68ed8d5 (diff)
downloadopenbsd-ed759aa6a877b98293e7fa74ea83ad183ea1157d.tar.gz
openbsd-ed759aa6a877b98293e7fa74ea83ad183ea1157d.tar.bz2
openbsd-ed759aa6a877b98293e7fa74ea83ad183ea1157d.zip
Add a test program for getopt(3) that is adequate for manual testing
and a compact test suite for getopt(3) intended automated regression testing, both written from scratch. The suite is intended to provide full coverage, except that it doesn't test manual changes of optind and optreset and except that it so far avoids the situation where we have a known bug.
-rw-r--r--src/regress/lib/libc/Makefile4
-rw-r--r--src/regress/lib/libc/getopt/Makefile10
-rw-r--r--src/regress/lib/libc/getopt/getopt-test.c59
-rw-r--r--src/regress/lib/libc/getopt/getopt.sh103
4 files changed, 174 insertions, 2 deletions
diff --git a/src/regress/lib/libc/Makefile b/src/regress/lib/libc/Makefile
index b1a55f1c1f..3d0712f951 100644
--- a/src/regress/lib/libc/Makefile
+++ b/src/regress/lib/libc/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.54 2020/01/13 15:35:57 bluhm Exp $ 1# $OpenBSD: Makefile,v 1.55 2020/03/23 03:01:21 schwarze Exp $
2 2
3SUBDIR+= _setjmp 3SUBDIR+= _setjmp
4SUBDIR+= alloca arc4random-fork atexit 4SUBDIR+= alloca arc4random-fork atexit
@@ -7,7 +7,7 @@ SUBDIR+= cephes cxa-atexit
7SUBDIR+= db dirname 7SUBDIR+= db dirname
8SUBDIR+= env explicit_bzero 8SUBDIR+= env explicit_bzero
9SUBDIR+= fmemopen fnmatch fpclassify fread 9SUBDIR+= fmemopen fnmatch fpclassify fread
10SUBDIR+= gcvt getaddrinfo getcap getopt_long glob 10SUBDIR+= gcvt getaddrinfo getcap getopt getopt_long glob
11SUBDIR+= hsearch 11SUBDIR+= hsearch
12SUBDIR+= ieeefp ifnameindex 12SUBDIR+= ieeefp ifnameindex
13SUBDIR+= ldexp locale longjmp 13SUBDIR+= ldexp locale longjmp
diff --git a/src/regress/lib/libc/getopt/Makefile b/src/regress/lib/libc/getopt/Makefile
new file mode 100644
index 0000000000..bdafc965fe
--- /dev/null
+++ b/src/regress/lib/libc/getopt/Makefile
@@ -0,0 +1,10 @@
1# $OpenBSD: Makefile,v 1.1 2020/03/23 03:01:21 schwarze Exp $
2
3REGRESS_TARGETS = getopt
4PROG = getopt-test
5MAN =
6
7getopt: ${PROG}
8 sh ${.CURDIR}/getopt.sh
9
10.include <bsd.regress.mk>
diff --git a/src/regress/lib/libc/getopt/getopt-test.c b/src/regress/lib/libc/getopt/getopt-test.c
new file mode 100644
index 0000000000..40901dcfcf
--- /dev/null
+++ b/src/regress/lib/libc/getopt/getopt-test.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: getopt-test.c,v 1.1 2020/03/23 03:01:21 schwarze Exp $ */
2/*
3 * Copyright (c) 2020 Ingo Schwarze <schwarze@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
20
21/*
22 * Process command line options and arguments according to the
23 * optstring in the environment variable OPTS. Write:
24 * OPT(c) for an option "-c" without an option argument
25 * OPT(carg) for an option "-c" with an option argument "arg"
26 * ARG(arg) for a non-option argument "arg"
27 * NONE(arg) for a non-option argument "arg" processed with OPTS =~ ^-
28 * ERR(?c) for an invalid option "-c", or one lacking an argument
29 * ERR(:c) for an option "-c" lacking an argument while OPTS =~ ^:
30 */
31int
32main(int argc, char *argv[])
33{
34 char *optstring;
35 int ch;
36
37 if ((optstring = getenv("OPTS")) == NULL)
38 optstring = "";
39
40 opterr = 0;
41 while ((ch = getopt(argc, argv, optstring)) != -1) {
42 switch (ch) {
43 case '\1':
44 printf("NONE(%s)", optarg);
45 break;
46 case ':':
47 case '?':
48 printf("ERR(%c%c)", ch, optopt);
49 break;
50 default:
51 printf("OPT(%c%s)", ch, optarg == NULL ? "" : optarg);
52 break;
53 }
54 }
55 while (optind < argc)
56 printf("ARG(%s)", argv[optind++]);
57 putchar('\n');
58 return 0;
59}
diff --git a/src/regress/lib/libc/getopt/getopt.sh b/src/regress/lib/libc/getopt/getopt.sh
new file mode 100644
index 0000000000..97668fc262
--- /dev/null
+++ b/src/regress/lib/libc/getopt/getopt.sh
@@ -0,0 +1,103 @@
1#!/bin/sh
2#
3# $OpenBSD: getopt.sh,v 1.1 2020/03/23 03:01:21 schwarze Exp $
4#
5# Copyright (c) 2020 Ingo Schwarze <schwarze@openbsd.org>
6#
7# Permission to use, copy, modify, and distribute this software for any
8# purpose with or without fee is hereby granted, provided that the above
9# copyright notice and this permission notice appear in all copies.
10#
11# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
19# Run ./getopt-test once.
20# Function arguments:
21# 1. optstring argument for getopt(3)
22# 2. space-separated command line arguments
23# 3. expected output from ./getopt-test
24test1_getopt()
25{
26 result=$(OPTS=$1 ./getopt-test $2)
27 test "$result" == "$3" && return
28 echo "OPTS=$1 ./getopt-test $2"
29 echo "expected: $3"
30 echo "result: $result"
31 irc=1
32}
33
34# Test both without and with the optstring modifier "+",
35# verifying that it makes no difference.
36test2_getopt()
37{
38 test1_getopt "$1" "$2" "$3"
39 test1_getopt "+$1" "$2" "$3"
40}
41
42# Also test with the GNU "-" optstring modifier,
43# veryfying that it only changes ARG() to NONE().
44# This test function is inadequate in two situations:
45# a) options follow non-option arguments that terminate option processing
46# b) or any arguments follow explicit "--".
47# In these cases, use test2_getopt() plus a separate test1_getopt(-...).
48test3_getopt()
49{
50 test2_getopt "$1" "$2" "$3"
51 test1_getopt "-$1" "$2" $(echo $3 | sed s/ARG/NONE/g)
52}
53
54irc=0
55
56# isolated options without arguments
57test3_getopt ax '-a -x arg' 'OPT(a)OPT(x)ARG(arg)'
58test3_getopt ax '-a -y arg' 'OPT(a)ERR(?y)ARG(arg)'
59test1_getopt :ax '-a -y arg' 'OPT(a)ERR(?y)ARG(arg)'
60
61# grouped options without arguments
62test3_getopt ax '-ax arg' 'OPT(a)OPT(x)ARG(arg)'
63test3_getopt ax '-ay arg' 'OPT(a)ERR(?y)ARG(arg)'
64test1_getopt :ax '-ay arg' 'OPT(a)ERR(?y)ARG(arg)'
65
66# non-option arguments terminating option processing
67test2_getopt ax '-a arg -x' 'OPT(a)ARG(arg)ARG(-x)'
68test1_getopt -ax '-a arg1 -x arg2' 'OPT(a)NONE(arg1)OPT(x)NONE(arg2)'
69test2_getopt ax '-a -- -x' 'OPT(a)ARG(-x)'
70test1_getopt -ax '-a -- -x' 'OPT(a)ARG(-x)'
71test2_getopt ax '-a - -x' 'OPT(a)ARG(-)ARG(-x)'
72test1_getopt -ax '-a - -x arg' 'OPT(a)NONE(-)OPT(x)NONE(arg)'
73
74# the '-' option only works when isolated
75test3_getopt a- '-a - -x arg' 'OPT(a)OPT(-)ERR(?x)ARG(arg)'
76test1_getopt :a- '-a - -x arg' 'OPT(a)OPT(-)ERR(?x)ARG(arg)'
77test1_getopt --a '-a - -x arg' 'OPT(a)OPT(-)ERR(?x)NONE(arg)'
78test3_getopt ax '-a-x arg' 'OPT(a)ERR(?-)OPT(x)ARG(arg)'
79test3_getopt a-x '-a-x arg' 'OPT(a)ERR(?-)OPT(x)ARG(arg)'
80
81# the ':' option never works
82test1_getopt ::a '-:a arg' 'ERR(?:)OPT(a)ARG(arg)'
83test1_getopt :::a '-: arg -a' 'ERR(?:)ARG(arg)ARG(-a)'
84
85# isolated options with arguments
86test3_getopt o: '-o' 'ERR(?o)'
87test1_getopt :o: '-o' 'ERR(:o)'
88test3_getopt o:x '-o arg -x arg' 'OPT(oarg)OPT(x)ARG(arg)'
89test3_getopt o::x '-oarg -x arg' 'OPT(oarg)OPT(x)ARG(arg)'
90test2_getopt o::x '-o arg -x' 'OPT(o)ARG(arg)ARG(-x)'
91test1_getopt -o::x '-o arg1 -x arg2' 'OPT(o)NONE(arg1)OPT(x)NONE(arg2)'
92test3_getopt o:x '-o -- -x arg' 'OPT(o--)OPT(x)ARG(arg)'
93
94# grouped options with arguments
95test3_getopt ao: '-ao' 'OPT(a)ERR(?o)'
96test1_getopt :ao: '-ao' 'OPT(a)ERR(:o)'
97test3_getopt ao:x '-ao arg -x arg' 'OPT(a)OPT(oarg)OPT(x)ARG(arg)'
98test3_getopt ao::x '-aoarg -x arg' 'OPT(a)OPT(oarg)OPT(x)ARG(arg)'
99test2_getopt ao::x '-ao arg -x' 'OPT(a)OPT(o)ARG(arg)ARG(-x)'
100test1_getopt -ao::x '-ao arg1 -x arg2' 'OPT(a)OPT(o)NONE(arg1)OPT(x)NONE(arg2)'
101test3_getopt ao:x '-ao -- -x arg' 'OPT(a)OPT(o--)OPT(x)ARG(arg)'
102
103exit $irc