1 #!/usr/bin/env bash
2 #
3 # Test set flags, sh flags.
4
5 ### $- with -c
6 # dash's behavior seems most sensible here?
7 $SH -o nounset -c 'echo $-'
8 # stdout: u
9 # OK bash stdout: huBc
10 # OK mksh stdout: uhc
11 # status: 0
12
13 ### $- with pipefail
14 set -o pipefail -o nounset
15 echo $-
16 # stdout: u
17 # status: 0
18 # OK bash stdout: huB
19 # OK mksh stdout: ush
20 # N-I dash stdout-json: ""
21 # N-I dash status: 2
22
23 ### sh -c
24 $SH -c 'echo hi'
25 # stdout: hi
26 # status: 0
27
28 ### empty -c input
29 # had a bug here
30 $SH -c ''
31 # stdout-json: ""
32 # status: 0
33
34 ### empty stdin
35 # had a bug here
36 echo -n '' | $SH
37 # stdout-json: ""
38 # status: 0
39
40 ### args are passed
41 $SH -c 'argv.py "$@"' dummy a b
42 # stdout: ['a', 'b']
43
44 ### args that look like flags are passed after script
45 script=$TMP/sh1.sh
46 echo 'argv.py "$@"' > $script
47 chmod +x $script
48 $SH $script --help --help -h
49 # stdout: ['--help', '--help', '-h']
50
51 ### args that look like flags are passed after -c
52 $SH -c 'argv.py "$@"' --help --help -h
53 # stdout: ['--help', '-h']
54
55 ### pass short options on command line
56 $SH -e -c 'false; echo status=$?'
57 # stdout-json: ""
58 # status: 1
59
60 ### pass long options on command line
61 $SH -o errexit -c 'false; echo status=$?'
62 # stdout-json: ""
63 # status: 1
64
65 ### can continue after unknown option
66 # dash and mksh make this a fatal error no matter what.
67 set -o errexit
68 set -o STRICT || true # unknown option
69 echo hello
70 # stdout: hello
71 # status: 0
72 # BUG dash/mksh stdout-json: ""
73 # BUG dash status: 2
74 # BUG mksh status: 1
75
76 ### set with both options and argv
77 set -o errexit a b c
78 echo "$@"
79 false
80 echo done
81 # stdout: a b c
82 # status: 1
83
84 ### nounset
85 echo "[$unset]"
86 set -o nounset
87 echo "[$unset]"
88 echo end # never reached
89 # stdout: []
90 # status: 1
91 # OK dash status: 2
92
93 ### -u is nounset
94 echo "[$unset]"
95 set -u
96 echo "[$unset]"
97 echo end # never reached
98 # stdout: []
99 # status: 1
100 # OK dash status: 2
101
102 ### nounset with "$@"
103 set a b c
104 set -u # shouldn't touch argv
105 echo "$@"
106 # stdout: a b c
107
108 ### set -u -- clears argv
109 set a b c
110 set -u -- # shouldn't touch argv
111 echo "$@"
112 # stdout:
113
114 ### set -u -- x y z
115 set a b c
116 set -u -- x y z
117 echo "$@"
118 # stdout: x y z
119
120 ### reset option with long flag
121 set -o errexit
122 set +o errexit
123 echo "[$unset]"
124 # stdout: []
125 # status: 0
126
127 ### reset option with short flag
128 set -u
129 set +u
130 echo "[$unset]"
131 # stdout: []
132 # status: 0
133
134 ### set -eu (flag parsing)
135 set -eu
136 echo "[$unset]"
137 echo status=$?
138 # stdout-json: ""
139 # status: 1
140 # OK dash status: 2
141
142 ### -n for no execution (useful with --ast-output)
143 # NOTE: set +n doesn't work because nothing is executed!
144 echo 1
145 set -n
146 echo 2
147 set +n
148 echo 3
149 # stdout-json: "1\n"
150 # status: 0
151
152 ### xtrace
153 echo 1
154 set -o xtrace
155 echo 2
156 # stdout-json: "1\n2\n"
157 # stderr: + echo 2
158
159
160 ### pipefail
161 # NOTE: the sleeps are because osh can fail non-deterministically because of a
162 # bug. Same problem as PIPESTATUS.
163 { sleep 0.01; exit 9; } | { sleep 0.02; exit 2; } | { sleep 0.03; exit 0; }
164 echo $?
165 set -o pipefail
166 { sleep 0.01; exit 9; } | { sleep 0.02; exit 2; } | { sleep 0.03; exit 0; }
167 echo $?
168 # stdout-json: "0\n2\n"
169 # status: 0
170 # N-I dash stdout-json: "0\n"
171 # N-I dash status: 2
172
173 ### shopt -p -o
174 shopt -po nounset
175 set -u
176 shopt -po nounset
177 # stdout-json: "set +o nounset\nset -o nounset\n"
178 # N-I dash/mksh stdout-json: ""
179 # N-I dash/mksh status: 127
180
181 ### shopt -p
182 shopt -p nullglob
183 shopt -s nullglob
184 shopt -p nullglob
185 # stdout-json: "shopt -u nullglob\nshopt -s nullglob\n"
186 # N-I dash/mksh stdout-json: ""
187 # N-I dash/mksh status: 127